vue虚拟DOM

202 阅读2分钟

这是我参与11月更文挑战的第11天,活动详情查看:2021最后一次更文挑战

一、虚拟DOM概念

虚拟DOM(Virtual Dom)是对DOM的JS抽象表示,它们是js对象,一棵树,可以描述DOM结构和关系,应用的各种状态变化会作用于虚拟DOM,最终映射到DOM上。

在虚拟DOM变成真实DOM的过程中,可以做跨平台处理或浏览器兼容性处理。

常见的虚拟DOM类库有virtual-dom和snabbdom,vue中的虚拟DOM是基于snabbdom实现

二、虚拟DOM变为真实DOM

在上面的流程图中,我们可以直到虚拟DOM变成真实DOM是通过patch实现的。patch会进行树的比较,就是增删改:

  • new VNode不存在就删除。
  • old VNode不存在就新增。
  • 都存在就进行diff算法更新修改。

比较两个VNode,一般是通过属性更新、文本更新、子节点更新三种操作

具体规则:

  • 新老节点都有children子节点,就对子节点进行diff操作,调用UpdateChildren
  • 新节点有children但是老节点没有子节点,就要先清空老节点的内容,然后新增子节点
  • 新节点没有children但是老节点有子节点,就要删掉老节点的所有子节点
  • 如果新老节点都没有子节点,就直接替换。

其中使用updateChildren方法,高效的比对两个新旧节点的子节点算出最小操作补丁。平时我们遇到这种情况都是用双重for循环进行对比,但是vue使用diff算法进行了优化。当然,每个DOM节点都有key,主要作用是判断两个vnode是否是相同的节点

三、总结

优点

  • 虚拟DOM更轻量级,且速度快;当他们发生变化的时候通过新旧虚拟DOM比对可以得到最小的DOM操作量,配合异步更新策略减少刷新频率,从而提升性能。

    patch(vnode,h('div',obj.foo));

  • 可以跨平台;在虚拟DOM更新转换为不同运行时特殊操作实现跨平台,例如uniapp

  • 兼容性高;可以在patch中加入兼容性代码,提高可操作性。

历史

  1. vue1.0里有细粒度的数据变化检测,是不需要虚拟DOM的,但是细粒度造成了大量的开销,但是项目很大的情况下是不能接受的。
  2. vue2.0选择了中等粒度的解决办法,每一个组件一个watcher实例,这样的状态变化时只能通知到组件,再通过引入虚拟DOM进行对比和渲染。