在Vue中,diff算法是虚拟DOM(Virtual DOM)的核心优化机制,用于高效比较新旧虚拟DOM树的差异,并最小化真实DOM操作。
1. 核心目标
高效更新:通过对比新旧虚拟DOM,找出最小差异,避免全量渲染,提升性能。
减少DOM操作:真实DOM操作成本高,diff算法只更新必要部分。
2. 核心原则
同层比较(最重要原则):
只比较同一层级的节点,不跨层级比较(如父节点和子节点不直接对比)。
若节点类型不同(如
div→p),直接销毁旧节点及其子树,创建新节点。
3. 关键流程
(1) 节点比较
类型相同:继续比较子节点和属性。
类型不同:直接替换整个节点(包括子树)。
文本节点:直接比较文本内容,不同则更新。
(2) 子节点优化(重点)
双端比较法(高效处理列表更新):
使用4个指针:
oldStart、oldEnd、newStart、newEnd。依次比较:
oldStartvsnewStart(头头)oldEndvsnewEnd(尾尾)oldStartvsnewEnd(头尾)oldEndvsnewStart(尾头)
匹配成功则移动指针,否则通过
key查找匹配节点。
key的作用(必考点):唯一标识节点,帮助diff算法高效复用节点。
无
key时:采用“就地复用”策略,可能导致渲染错误(如列表顺序错乱)。有
key时:通过key匹配旧节点,实现移动、复用或删除,避免冗余操作。
4. 性能优化点
时间复杂度:O(n),通过双端比较和
key优化,避免O(n³)的暴力对比。惰性更新:非活跃组件不触发diff(如
v-if为false时)。静态提升:编译时标记静态节点,diff时直接跳过。
5. 面试金句总结
“Vue的diff算法基于同层比较和双端优化,通过
key高效复用节点,仅更新差异部分。核心是最小化DOM操作,避免全量渲染,提升性能。”
常见面试追问
Q:为什么不用
index做key?
A:index在列表增删时会变化,导致节点误匹配(如顺序错乱),应使用唯一ID。Q:diff算法和React的异同?
A:核心思想相似(同层比较),但Vue采用双端比较,React早期用递归(React 16后改用Fiber架构)。Q:哪些场景会触发diff?
A:响应式数据变化(如data更新)、props变化、强制更新(this.$forceUpdate())等。