为什么会有虚拟 DOM?
DOM 结构复杂时,每次操作 DOM 渲染引擎都需要进行重排、重绘或者合成操作,非常耗时,耗性能。需要一种方式来减少 JS 对 DOM 的操作,于是就有了虚拟 DOM。
虚拟 DOM 要解决的事情
- 将页面改变的内容应用到虚拟 DOM 上,而不是真实 DOM
- 虚拟 DOM 不立马渲染页面,而仅仅是调整虚拟 DOM 内部状态
- 在虚拟 DOM 收集到足够的改变时,再把这些变化一次性应用到真实 DOM
什么是虚拟 DOM?
下图为虚拟 DOM 的执行流程
创建阶段:依据数据创建出虚拟 DOM,然后由虚拟 DOM 创建出真实 DOM,生成完后触发渲染流水线输出到页面。
更新阶段:数据发生变化,根据新数据创建一个新的虚拟 DOM 树,然后与旧的比较,找出变化的地方,并把变化的地方一次性更新到真实的 DOM 树上,最后渲染引擎更新渲染流水线,生成新页面。
React Fiber 更新机制
React 最初比较虚拟 DOM 的过程是在递归函数里,核心算法是 reconciliation. 正常情况下很快,虚拟 DOM 结构一复杂时,执行比较函数会占据主线程比较久的时间,就会导致其他任务等待,造成页面卡顿。于是发明了新算法Fiber reconciler.
Fiber 的另一个称呼就是协程,在执行算法过程中让出主线程,就解决了以前Stack reconciler函数占用时间过久的问题。
双缓存与 MVC 视角下的虚拟 DOM
- 双缓存
当渲染复杂图像时,需要计算很多次才能完成,如果每计算一点就写入缓冲区,看到的页面效果就是一点一点显示出来,会让用户感受到界面闪烁。
使用双缓存,可以把计算机的中间结果存放在另一个缓冲区,等全部计算结束,缓冲区存储完整图形之后,再将该缓冲区的图形数据一次性复制到显示缓冲区,这样图像就会稳定输出。
虚拟 DOM 的 DOM 就相当于一个 buffer,它会在一次完整操作后将结果应用到 DOM 上,即减少了不必要的更新,还能保证 DOM 的稳定输出。
双缓存是一种经典的思路,应用在很多场合,能解决页面无效刷新和闪屏问题。
- MVC 模式

图中的控制器是用来监控 DOM 的变化,一旦 DOM 发生变化,控制器便通知模型,让其更新数据。
模型数据更新好之后,控制器会通知视图,告诉他模型数据发生变化。
视图收到数据后,根据数据生成新的虚拟 DOM。然后与之前虚拟 DOM 对比,找出变化节点。
然后将变化节点用到 DOM 上,触发 DOM 节点的更新。DOM 节点的更新又会触发后续一系列渲染流水线的变化,实现页面更新。
