[TOC]
Vue diff算法详解
Vue diff 是 Vue 框架中用于比较虚拟 DOM(Virtual DOM)差异的算法。它的主要作用是在数据发生变化时,高效地更新用户界面。
diff算法特点:
- 1、比较只会在同层级进行, 不会跨层级比较
- 2、在diff比较的过程中,循环从两边向中间比较
- 3、如果添加了key属性,在第二条的基础上,还会根据key属性提高比较效率
1. diff 算法作用
Vue diff 是 Vue 框架中用于高效更新视图的重要机制。它通过比较虚拟 DOM(Virtual DOM)的差异,只更新实际发生变化的部分,从而减少不必要的 DOM 操作,提高了应用程序的性能。
1、提高性能(减少DOM操作):通过只更新实际发生变化的部分,Vue diff 减少了不必要的 DOM 操作,从而提高了应用程序的性能。这对于需要频繁更新视图的应用程序尤为重要。
2、
减少闪烁:由于 Vue diff 只更新实际发生变化的部分
,因此可以减少视图的闪烁,提高用户体验。3、提高开发效率:Vue diff 使得开发人员无需关心具体的 DOM 操作,而是专注于业务逻辑的开发。这降低了开发的复杂性,提高了开发效率。
4、
跨平台支持:Vue diff 基于虚拟 DOM 实现,因此可以在不同的平台和浏览器上运行
。这使得 Vue 应用程序具有良好的跨平台支持。
总之,Vue diff 是 Vue 框架中用于高效更新视图的重要机制,它提高了应用程序的性能、用户体验和开发效率,为开发高质量的 Vue 应用程序提供了有力支持。
2. diff 算法的过程
假设我们有两棵虚拟 DOM 树,如下所示:
// 旧虚拟 DOM 树
const oldTree = {
tag: 'ul',
children: [
{ tag: 'li', key: 'a', text: 'a' },
{ tag: 'li', key: 'b', text: 'b' },
{ tag: 'li', key: 'c', text: 'C' },
{ tag: 'li', key: 'd', text: 'd' },
]
}
// 新虚拟 DOM 树
const newTree = {
tag: 'ul',
children: [
{ tag: 'li', key: 'b', text: 'b' },
{ tag: 'li', key: 'e', text: 'e' },
{ tag: 'li', key: 'd', text: 'd' },
{ tag: 'li', key: 'c', text: 'c' }
]
}
diff算法分两种情况:
1、dom元素添加了key属性,如代码示例中的key属性。
2、dom元素没有key,比如示例代码children元素中删除key属性。
设置key和不设置key的区别:
不设置key,新dom和旧dom智慧进行头尾两端的相互比较。设置key后,除了头尾两端的比较外,还会从用key生成的对象oldKeyToIdx
中查找匹配的节点,所以为节点设置key可以更高效的利用dom。
2.1 没有设置key情况
由于vue diff算法是新旧虚拟dom两端同时进行比较:
1、新dom开始端节点b没有在旧dom两端找到,因此在结果dom创建一个新节点b。新dom开始端移到第二个节点e,旧dom两端节点索引没动。
2、新dom开始端节点e没有在旧dom两端找到,因此在结果dom创建新节点e。新dom开始端移到第三个节点d。旧dom两端节点索引没动。
3、新dom开始端节点d跟旧dom的末端索引相同,因此,把旧dom末端节点d放到结果dom后面。新dom开始端移到第四个节点c。旧dom末端索引向前移到节点c。
4、新dom开始端节点c跟旧dom的末端索引相同,因此,把旧dom末端节点c放到结果dom后面。由于新dom两端索引相同,结束diff比较,
5、由于新dom两端索引相同,结束diff比较。由于旧dom的a、b两个节点没有用了,因此移除。
2.2 设置了key
由于dom节点设置了key,因此,在头尾两端的比较外后,如果没有找到相同的节点,那么新dom开始索引节点还会用key在旧dom中的key列表里面找一遍,到后后就移到最终结果中,因此新dom第一个节点b不需要重新创建,只需要从旧dom中一过来就可以。