
Vue 3 的 Diff 算法在 Vue 2 的基础上进行了全面重构和优化核心改进集中在编译时静态分析和运行时双端 Diff 的算法升级两大方向。这些优化让 Vue 3 在大型列表渲染和频繁更新的场景下性能大幅提升。一、编译时优化从全量比对到跳过静态节点Vue 3 引入了静态提升和Block Tree让 Diff 算法在编译阶段就标记出不会变化的部分运行时直接跳过。1. 静态提升Static HoistingVue 2 中每次重新渲染都会重新创建所有 VNode虚拟节点并进行 Diff。Vue 3 则将静态节点不依赖响应式数据的节点提升到渲染函数外部只创建一次复用多次。!-- 模板 -- div p静态文本/p p{{ dynamic }}/p /divVue 2每次更新都会重新创建两个p的 VNode。Vue 3第一个p被标记为静态只创建一次后续更新直接复用Diff 时直接跳过。2. Block Tree 与 Patch FlagsVue 3 将模板编译为嵌套的 Block动态节点集合每个 Block 会收集其内部所有动态节点如绑定v-for、{{}}、v-if的节点。Patch Flags在编译时为每个动态节点标记更新类型如TEXT文本变化、CLASS类变化、STYLE样式变化。Diff 时只遍历 Block 中的动态节点且只对比标记的特定属性不再遍历整棵树大幅减少比对量。// 编译后的 VNode 示例 { type: p, children: 动态文本, patchFlag: 1 // 1 表示 TEXT 类型只检查文本变化 }二、运行时 Diff 算法优化从双端比较到最长递增子序列Vue 2 使用双端比较策略通过四个指针头尾相互比较来尽可能复用 DOM 节点。Vue 3 在保留双端比较的基础上针对乱序情况引入了最长递增子序列Longest Increasing Subsequence, LIS算法极大减少了 DOM 移动次数。核心场景列表重排序假设旧列表为[a, b, c, d, e]新列表为[a, c, e, b, d]。Vue 2 的双端比较会进行多次移动操作最终将节点调整到正确位置。Vue 3 的 LIS 优化先通过 key 找到新旧节点的映射关系。计算新列表中需要移动的最小节点集合即最长递增子序列。只移动不在递增子序列中的节点其余节点保持不动。在上述例子中最长递增子序列是[a, c, e]索引[0, 2, 4]Vue 3 只会移动b和d而a, c, e保持原位移动次数从 3-4 次降为 2 次。三、其他关键优化点优化项Vue 2Vue 3事件缓存每次重新渲染都会重新生成内联函数缓存事件处理函数复用同一引用Fragment 支持不支持多根节点必须包裹支持多根节点内部自动生成 Block静态 Props 提升所有 props 都参与 Diff静态 props如idfixed被提升跳过 Diff更快的 VNode 创建使用new VNode()构造函数使用createVNode函数性能提升约 2 倍性能提升数据官方 benchmark 显示Vue 3 的 Diff 性能在以下场景有显著提升列表更新带 key提升约50%~100%静态内容渲染提升约200%~300%得益于静态提升内存占用减少约30%~50%总结优化的核心思想Vue 3 的 Diff 优化可以用一句话概括编译时多标记运行时少比对。编译时通过静态提升、Block Tree、Patch Flags 提前标记哪些会变、怎么变。运行时利用 LIS 算法最小化 DOM 移动次数结合缓存复用事件和静态 Props。这些优化让 Vue 3 在处理大型表格、长列表、频繁更新的动画场景时性能远超 Vue 2。