前提:知晓虚拟 DOM 的意义在于使找出差异性能消耗的最小化
从 Vue2 说起到 Vue3 的 Diff 算法实现:
-
在 Vue2 中我们使用双端 Diff 算法进行 Vnode 的差异化对比:
- 在新旧两组子节点的四个断点之间进行比较,并视图找到可复用的节点;
-
在 Vue3 中我们使用快速 Diff 算法进行 Vnode 的差异化对比:
- 该算法最早运用于 ivi、inferno 这两个框架,因为它在实测中性能最优所以 Vue3 在实现时借鉴并扩展了他们;
- 它借鉴了文本 Diff 中的预处理思路,先处理新旧两组子节点中相同的前置节点和后置节点。当前置节点和后置节点全部处理完毕后,如果无法简单的通过挂载(卸载)来处理新增节点(已经不存在)节点来完成更新,则需要通过节点的关系来构造一个最长递增子序列。而该子序列所指向的节点是不需要进行移动的,以保证以最小的代价达到最优的 dom 更新。
我们可以思考一下:
- 不考虑效率即不使用 diff 算法,我们可以通过怎样的方式做到节点的更新?
- 一个很笨的方法:通过循环的方式卸载所有的旧子节点,挂载新子节点
- 简单 diff 算法:
- 在 Vue3 的实现中利用到了简单 diff 算法的一条规律:在旧 children 中寻找具有相同 key 值的节点的过程中,遇到的最大索引;
- 通过遍历新旧两组子节点较少的那一组,并逐个调用 patch 进行打补丁。然后比较新旧点的数量:新的一组子节点较多说明有新节点需要进行挂载,旧的一组子节点较多则说明有节点需要卸载。