24 虚拟DOM

Posted by CodingWithAlice on April 18, 2021

24 虚拟DOM

DOM的缺陷

1、JS 操纵 DOM 是会影响到整个渲染流水线

2、重排/重绘 在复杂页面非常耗时(主线程)

3、对 DOM 的不当操作引起 强制同步布局和布局抖动 的问题,大大降低了渲染效率

虚拟DOM解决的问题

1、页面的改变直接应用到虚拟DOM上,而不是DOM

2、有变化后,虚拟DOM并不直接渲染页面,而是仅调整虚拟DOM的内部状态

3、虚拟DOM收集到足够的改变时,才把变化一次性应用到真实DOM上(异步)

什么是虚拟DOM(react框架为例)

下图是react框架中虚拟DOM的执行流程:

  • 1、创建阶段

    JSX 和基础数据创建出虚拟 DOM

    –> 由虚拟 DOM 树创建出真实 DOM 树

    –> 真实的 DOM 树生成完后,再触发渲染流水线往屏幕输出页面

  • 2、更新阶段

    根据变化的数据创建一个新的虚拟 DOM 树

    –> React 比较两个树,并把变化的地方一次性更新到真实的 DOM 树上

    –> 渲染引擎更新渲染流水线,并生成新的页面

image-20210418135943571

注意:在react中,将diff算法(DOM树比较过程)已经从以前的 Stack reconciler(在主线程调用递归函数),更新到 Fiber reconciler(利用协程,在执行算法的过程中出让主线程

双缓存和MVC视角下的虚拟DOM

1、双缓存

​ 之前论述过图片显示读取的缓冲区,为了避免一张复杂图像被一部分一部分得显示出来,先将计算的 中间结果存放在另一个缓冲区 中,等全部的计算结束,该缓冲区已经 存储了完整的图形之后,再将该缓冲区的图形数据 一次性复制到显示缓冲区,这样就使得整个图像的输出非常稳定。

​ 同样的设计模式也可以套用在虚拟 DOM 的实现上,和图形显示一样,它会在 完成一次完整的操作之后,再把结果应用到 DOM 上,这样就能减少一些不必要的更新,同时还能保证 DOM 的稳定输出。

2、MVC模式

MVC - 将数据和视图分离,视图和模型之间不允许直接通信,通过控制器来完成通讯,减小耦合度,易于维护(MVVM、MVP都是MVC的衍生)

image-20210418140057020

可以看下虚拟DOM在MVC模式中的功能:

image-20210418140147438

细化分析上图:

1、控制器 –> 用来监控 DOM 的变化:一旦 DOM 发生变化,控制器便会通知模型,让其更新数据

2、事件触发,模型数据更新好之后,控制器会通知视图,告诉它模型的数据发生了变化

3、视图接收到更新消息之后,会根据模型所提供的数据来生成 新的虚拟 DOM

4、新的虚拟 DOM 生成好之后,就需要 与之前的虚拟 DOM 进行比较,找出变化的节点

5、比较出变化的节点之后,React 将变化的虚拟节点应用到 DOM 上,这样就会触发 DOM 节点的更新

6、DOM 节点的变化又会触发后续一系列 渲染流水线 的变化,从而实现页面的更新