vue diff实现
Vue Diff 算法实现原理
Vue 的 Diff 算法是虚拟 DOM 更新的核心,用于高效比较新旧虚拟节点的差异并最小化 DOM 操作。以下是其核心实现逻辑:
同层级比较
Diff 算法只在同层级节点间比较,跨层级操作会直接销毁旧节点并创建新节点。这种策略减少了比较复杂度,从 O(n^3) 优化到 O(n)。
双端比较策略
Vue 采用双指针方式同时遍历新旧子节点数组,通过四种命中查找优化比较效率:
- 新前旧前:比较新旧节点数组的第一个节点
- 新后旧后:比较新旧节点数组的最后一个节点
- 新后旧前:比较新数组最后一个节点与旧数组第一个节点
- 新前旧后:比较新数组第一个节点与旧数组最后一个节点
function updateChildren(parentElm, oldCh, newCh) {
let oldStartIdx = 0
let newStartIdx = 0
let oldEndIdx = oldCh.length - 1
let oldStartVnode = oldCh[oldStartIdx]
let oldEndVnode = oldCh[oldEndIdx]
let newEndIdx = newCh.length - 1
let newStartVnode = newCh[newStartIdx]
let newEndVnode = newCh[newEndIdx]
// ...比较逻辑
}
Key 的重要性
为 v-for 列表项设置唯一 key 能帮助算法准确识别节点身份,避免不必要的重新渲染。没有 key 时会采用就地复用策略,可能导致状态错乱。
节点复用判断
当找到相同节点时,Vue 会复用 DOM 元素并更新变化的部分属性。比较过程包括:
- 标签名是否相同
- key 是否相同
- 是否是静态节点
- 数据属性是否需要更新
差异更新类型
根据比较结果执行不同更新操作:
- 节点相同:递归比较子节点
- 节点不同:创建新节点并替换旧节点
- 多余旧节点:移除不再需要的节点
- 新增节点:插入新创建的节点
源码核心逻辑
Vue 的 patch 函数是 Diff 算法的入口:

function patchVnode(oldVnode, vnode) {
if (oldVnode === vnode) return
const elm = vnode.elm = oldVnode.elm
const oldCh = oldVnode.children
const ch = vnode.children
if (!vnode.text) {
if (oldCh && ch) {
if (oldCh !== ch) updateChildren(elm, oldCh, ch)
} else if (ch) {
addVnodes(elm, null, ch, 0, ch.length - 1)
} else if (oldCh) {
removeVnodes(elm, oldCh, 0, oldCh.length - 1)
}
} else if (oldVnode.text !== vnode.text) {
setTextContent(elm, vnode.text)
}
}
这种差异比较机制使 Vue 能在最小 DOM 操作下完成视图更新,兼顾性能和开发便利性。






