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 树上
–> 渲染引擎更新渲染流水线,并生成新的页面
注意:在react中,将diff算法(DOM树比较过程)已经从以前的 Stack reconciler(在主线程调用递归函数),更新到 Fiber reconciler(利用协程,在执行算法的过程中出让主线程)
双缓存和MVC视角下的虚拟DOM
1、双缓存
之前论述过图片显示读取的缓冲区,为了避免一张复杂图像被一部分一部分得显示出来,先将计算的 中间结果存放在另一个缓冲区 中,等全部的计算结束,该缓冲区已经 存储了完整的图形之后,再将该缓冲区的图形数据 一次性复制到显示缓冲区,这样就使得整个图像的输出非常稳定。
同样的设计模式也可以套用在虚拟 DOM 的实现上,和图形显示一样,它会在 完成一次完整的操作之后,再把结果应用到 DOM 上,这样就能减少一些不必要的更新,同时还能保证 DOM 的稳定输出。
2、MVC模式
MVC - 将数据和视图分离,视图和模型之间不允许直接通信,通过控制器来完成通讯,减小耦合度,易于维护(MVVM、MVP都是MVC的衍生)
可以看下虚拟DOM在MVC模式中的功能:
细化分析上图:
1、控制器 –> 用来监控 DOM 的变化:一旦 DOM 发生变化,控制器便会通知模型,让其更新数据
2、事件触发,模型数据更新好之后,控制器会通知视图,告诉它模型的数据发生了变化
3、视图接收到更新消息之后,会根据模型所提供的数据来生成 新的虚拟 DOM
4、新的虚拟 DOM 生成好之后,就需要 与之前的虚拟 DOM 进行比较,找出变化的节点
5、比较出变化的节点之后,React 将变化的虚拟节点应用到 DOM 上,这样就会触发 DOM 节点的更新
6、DOM 节点的变化又会触发后续一系列 渲染流水线 的变化,从而实现页面的更新