vue diff实现
Vue Diff 算法实现原理
Vue 的虚拟 DOM Diff 算法(即 patch 过程)是其高效渲染的核心,主要通过对比新旧虚拟节点的差异,最小化 DOM 操作。以下是关键实现要点:
同层级比较
Vue 的 Diff 算法仅在同层级节点间比较,跨层级移动节点会直接销毁重建。这种设计以时间复杂度 O(n) 实现高效对比,而非传统树 Diff 的 O(n³)。
双端比较策略
处理子节点列表时,Vue 采用双端指针优化:
- 初始化四个指针:旧列表头(oldStart)、旧列表尾(oldEnd)、新列表头(newStart)、新列表尾(newEnd)
- 依次比较四种可能匹配:
- oldStart 与 newStart
- oldEnd 与 newEnd
- oldStart 与 newEnd
- oldEnd 与 newStart
- 若匹配则移动对应指针,否则进入传统遍历查找
while (oldStartIdx <= oldEndIdx && newStartIdx <= newEndIdx) {
if (isSameVnode(oldStartVnode, newStartVnode)) {
patchVnode(oldStartVnode, newStartVnode)
oldStartVnode = oldChildren[++oldStartIdx]
newStartVnode = newChildren[++newStartIdx]
}
else if (isSameVnode(oldEndVnode, newEndVnode)) {
// ...类似处理
}
// ...其他情况处理
}
key 的重要性
key 作为虚拟节点的唯一标识,帮助算法快速定位相同节点。无 key 时会导致不必要的重新渲染。
<!-- 推荐写法 -->
<div v-for="item in list" :key="item.id">{{ item.text }}</div>
节点复用策略
当判断为相同节点时(通过 sameVnode),Vue 会复用 DOM 元素仅更新属性/内容:
- 比较标签类型、key 值等
- 更新属性(class/style 等)
- 递归处理子节点(如果存在)
function sameVnode(a, b) {
return (
a.key === b.key &&
a.tag === b.tag &&
a.isComment === b.isComment &&
// ...其他条件
)
}
源码核心路径
Vue 2.x 实现主要位于:
/src/core/vdom/patch.js中的updateChildren方法/src/core/vdom/vnode.js中的节点定义
Vue 3 优化为基于位运算的快速 Diff 算法,在 packages/runtime-core/src/renderer.ts 中实现。







