vue3 Diff 算法的优化
vue2 是全量进行 diff,而 vue3 使用了静态标记,只对打标记的节点进行 diff vue2 中的虚拟 dom 是进行全量的对比,在运行时会对所有节点生成一个虚拟节点树,当页面数据发生变更后,会遍历判断虚拟 dom 所有节点(包括一些不会变化的节点)有没有发生变化;vue3 在 diff 算法中相比 vue2 增加了静态标记, 在模版编译时,编译器会在动态标签末尾加上 /_ Text_/ PatchFlag。也就是在生成 VNode 的时候,同时打上标记,patch 过程中就会判断这个标记来 Diff 优化流程,跳过一些静态节点对比
vue2、vue3 的 diff 算法实现差异主要体现在:处理完首尾节点后,对剩余节点的处理方式。
在 vue2 中是通过对旧节点列表建立一个 { key, oldVnode }的映射表,然后遍历新节点列表的剩余节点,根据 newVnode.key 在旧映射表中寻找可复用的节点,然后打补丁并且移动到正确的位置。 而 vue3 则是建立一个存储新节点数组中的剩余节点在旧节点数组上的索引的映射关系数组,建立完成这个数组后也即找到了可复用的节点,然后通过这个数组计算得到最长递增子序列,这个序列中的节点保持不动,然后将新节点数组中的剩余节点移动到正确的位置。
Vue3 的 diff 对比 Vue2 的优化部分
Vue2 是全量 Diff(当数据发生变化,它就会新生成一个 DOM 树,并和之前的 DOM 树进行比较,找到不同的节点然后更新。);Vue3 是静态标记 + 非全量 Diff(Vue 3 在创建虚拟 DOM 树的时候,会根据 DOM 中的内容会不会发生变化,添加一个静态标记。之后在与上次虚拟节点进行对比的时候,就只会对比这些带有静态标记的节点。) 使用最长递增子序列优化对比流程,可以最大程度的减少 DOM 的移动,达到最少的 DOM 操作
Vue3 的 diff 算法核心
基本原理 首先进行新老节点头尾对比,头与头、尾与尾对比,寻找未移动的节点。 然后创建一个新节点在旧节点中的位置的映射表,这个映射表的元素如果不为空,代表可复用。 然后根据这个映射表计算出最长递增子序列,这个序列中的结点代表可以原地复用。之后移动剩下的新结点到正确的位置即递增序列的间隙中。