Vue 的 Patch 过程本质是“按需更新”,通过同层比较、key 驱动复用、双端指针优化及分层细粒度更新,将时间复杂度控制在 O(n),避免整树重建。

Vue 的 Patch 过程本质是“按需更新”——它不重建整个 DOM,而是只找出新旧 VNode 之间真正变化的部分,再精准打补丁。这个过程高效的关键,在于限制比较范围、复用已有节点、以及用策略减少遍历次数。
同层比较,拒绝跨级跳跃
Vue 的 diff 只在相同层级的子节点之间进行,不会把父节点和孙子节点去比。比如一个 ul 下的 li 列表更新时,只会逐个对比新旧 li 节点,而不会把某个 li 和它的子 span 拿去比较。这避免了树形结构的指数级复杂度,把问题控制在线性范围内。
- 一旦发现某层节点类型不匹配(比如旧的是
div,新的是span),直接丢弃整棵旧子树,新建对应结构 - 组件节点也遵循同层原则:同名且 key 相同的组件会被复用实例,避免重复 mount/unmount
- 这种设计让 patch 时间复杂度稳定在 O(n),而不是传统树对比可能达到的 O(n³)
key 驱动的节点复用机制
key 不是可选项,它是 Vue 判断“这个节点是否还是它自己”的唯一可靠依据。没有 key 时,Vue 只能按顺序一一对照;有 key 后,就能建立映射关系,快速定位可复用节点。
递归分析 Vue 项目组件依赖,从入口文件生成组件层级图,支持 Vue 2/3,输出组件名、文件路径和属性。适用于分析组件结构、排查依赖或了解项目架构。
- 列表渲染中,
v-for必须绑定唯一、稳定的 key,否则移动、插入、删除都可能触发错误复用 - sameVnode 函数首先校验 key 是否一致,再比 tag、isComment、data 存在性等,任一不满足就视为不可复用
- key 相同但其他属性不同(如 class 或 text 改变),Vue 会复用 DOM 元素,只更新差异属性,跳过创建/销毁开销
双端指针优化子节点更新
Vue 3 的 patchKeyedChildren 采用双端比较策略,从新旧子节点数组的头尾同时开始匹配,大幅减少无效遍历。
- 先同步头部:旧[0] vs 新[0] → 匹配则 patch 并推进指针
- 再同步尾部:旧[last] vs 新[last] → 匹配则 patch 并倒退指针
- 头尾都失配后,构建 key → index 映射表,用最长递增子序列(LIS)算法确定最优移动路径
- 最终只做最少的 insert/move/remove 操作,比如列表项调换位置,DOM 元素会被复用并重新排序,而非删了重建
细粒度更新:属性、文本、子节点分层处理
patch 不是一股脑重写,而是分层决策:先判断节点类型,再决定如何更新内部内容。
- 文本节点:直接比对
text字段,不同就调用setTextContent - 元素节点:逐项比对
data中的 class、style、props、事件监听器,仅更新变更项 - 子节点:若双方都有 children,则进入
updateChildren流程;若一方为空,另一方直接批量挂载或清空 - 组件节点:复用实例后,触发
updated或beforeUpdate生命周期,再递归 patch 其内部 VNode

















