引言:
上一节说了key
的用途,而这个key属性,在vue的vnode
中至关重要,直接影响了虚拟DOM
的更新机制;
什么场景中会用到diff算法
如:修改响应式属性需要重新渲染页面,会重新执行render渲染函数
返回新虚拟DOM,拿到新的虚拟DOM后,需要进行patch
对比新旧虚拟DOM,在对比双方的子级节点,需要拿旧的虚拟DOM
的子级和新的虚拟DOM
子级进行patchChildren
比较双方子级元素的差异,并且双方子级都为数组的情况下(具有多个子级节点)就会使用到diff算法!
为什么要用diff算法呢?提高性能、提升加载渲染速度、最大限度的复用原DOM
主要为了对比对新旧Vnode
的差异,将相同的节点数据复用,只找新增、修改的虚拟DOM
进行创建并插入**(提高性能),元素发生位置变化时,只需要找出哪些元素需要移动(减少元素移动次数)**;
若不比较新旧节点,则每次更新都先对旧节点进行卸载,再重新挂载新节点,都需要先根据标签名创建真实节点,再进行挂载,这样每次卸载或挂载都会造成页面重排重绘,造成性能浪费!
vue3里面的DIFF
Vue3 引入了一个全新的编译策略和运行时优化,包括对 Diff 算法的改进。Vue3 的 Diff 算法带来了更好的性能和更少的内存消耗,主要得益于以下几点:
支持碎片化(Fragment):Vue3
支持碎片化,即允许组件有多个根节点,这在Vue2
中是只允许一个根节点。
静态节点提升:Vue3
在编译时会对静态节点进行提升,这些节点在更新时不会被重新创建,而是直接复用,从而减少渲染成本。
区块树(Block Tree):Vue3
引入了区块树概念,它可以跳过静态内容,快速定位到动态节点,减少的对比次数。
编译时优化:Vue3
在编译时会对模板进行静态提升,将不会变化的节点和属性提取出来,避免在每次渲染时都重新创建。
双端比较优化:Vue3
继续使用了双端比较算法,但是采用的是Map 数据结构
在细节上进行了优化,比如对于相同节点的处理更加高效。
Vue2 里面的 DIFF
Vue2 中的 Diff 算法,主要关注子节点的列表差异。它通过同级比较来工作,对新旧节点列表进行遍历,比较每个节点是否相同,然后根据需要进行创建、更新或移除操作。
同级比较:只比较同一层级的节点,不跨层级比较。
双端比较:Vue2 的 Diff
算法采用双端比较策略,从列表的两端(头部和尾部)开始比较,以尽量减少节点的移动次数,通过splice函数进行数组操作
,重写了数组的7中操作方法,有局限性。
更新策略:当头尾比较无法匹配时,Vue2
会尝试复用旧节点,通过更新节点的属性或子节点来匹配新的虚拟节点,同时将其移动到正确的位置,以减少 DOM
操作次数。
Vue2 的 Diff
算法有一些限制,比如:
同级比较:不会进行跨层级的节点比较,这可能导致一些不必要的DOM
操作。
静态节点优化:对于静态节点,Vue2
在构建虚拟DOM
树时会有一些优化,但在更新时,这些优化不会重复利用。
最后
Vue3 的 Diff 算法在 Vue2 的基础上进行了多项优化,使得虚拟 DOM 的更新更加快速和高效。这些优化包括更高效的节点比较、静态节点提升、块树优化等,这些改进有助于减少渲染时间,提高应用的性能。
主要有以下5种特性