Vue 3 的 Diff 算法通过 Block Tree 实现靶向定位,编译时将模板切分为动态块,仅更新标记区块,并结合 Patch Flag 进行查表式比对,使性能取决于动态节点数而非模板大小。

Vue 3 并不是靠“秒杀”赢的,而是把 Diff 算法从“全量扫描”变成“靶向定位”——Block Tree 是实现这一转变的核心机制。
Block Tree 让 Diff 不再遍历整棵树
传统 Diff(如 Vue 2)每次更新都要从根节点开始,递归比对整个虚拟 DOM 树,哪怕只改了一个文本,静态标题、导航栏、页脚这些完全不变的部分也得重新走一遍对比逻辑。
Block Tree 的做法是:在编译阶段就把模板按动态性切分成若干“块”(Block),每个块只包含真正可能变化的节点,以及它们的动态子节点。渲染时,Vue 只需更新那些被标记为“需要检查”的 Block,其余部分直接跳过。
- 静态内容(比如
)被提升(hoist)成常量,在初始化时创建一次,后续复用欢迎页
- 动态内容(比如
)被单独包裹进 Block,只在这个小范围内做 Diff{{ count }}
- 一个组件里可以有多个 Block,彼此独立更新,互不影响
Patch Flag + Block Tree = 精准定位变更点
光有 Block 还不够,Vue 3 同时在编译时给每个动态节点打上 Patch Flag(补丁标志),比如 1 表示仅文本变化、2 表示 class 变化、8 表示 props 变化。这些标志和 Block 配合,让 runtime 的 Diff 操作变成“查表式更新”:
Element Plus Vue3 桌面组件库。在开发 Vue 3.x 页面时调用,使用 Element Plus 组件(如 el-button、el-input、el-form、el-table 等)。
- 遇到
patchFlag: 1的节点,Diff 引擎只比对textContent,不检查 class、style、子节点 - 没有 Patch Flag 的节点,默认视为静态,直接跳过
- Block 内部的 Diff 不再是树形递归,而是一维数组比对,复杂度大幅下降
性能关系彻底反转:从“看模板大小”到“看动态节点数”
这是最根本的差异:
- Vue 2:组件模板越大,Diff 耗时越长;100 行模板中哪怕只有 1 行动态,也要处理全部 100 行
- Vue 3:Diff 耗时只取决于 Block 内动态节点的数量;模板再大,只要动态内容少,更新就快
- 实测场景:一个含 50 个静态 item 和 1 个动态计数器的列表,Vue 2 Diff 时间约 1.8ms,Vue 3 通常低于 0.2ms
不只是快,还更稳、更可预测
Block Tree 带来的不仅是性能提升,还有行为确定性增强:
- v-if / v-for 区域自动成块,分支切换不再引发整树重排
- Fragment 支持天然适配 Block 划分,多根节点不再需要无意义的包装 div
- 插槽(slot)内容是否更新,由其自身是否属于动态 Block 决定,避免 Vue 2 中父组件更新强制触发子组件重渲染的问题
不复杂但容易忽略:Block Tree 不是运行时猜测出来的,它依赖编译器的静态分析。所以写法会影响优化效果——比如带动态 key 的元素、使用 ref 或自定义指令的节点,就不会被提升,也就无法进入最优 Block 路径。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!










