静态内容提升、patch flags 与 block tree 是深度耦合的一体化机制:前者剔除静态节点不参与 diff,后者精准比对动态字段,block 则组织最小更新单元,三者协同使 diff 节点减少三分之二,性能呈乘法提升。

静态内容提升与 Patch Flags 不是各自独立的优化,而是深度耦合、缺一不可的一体化机制——前者让静态节点“不进场”,后者让动态节点“只动该动的地方”,二者叠加才真正释放 Vue3 的 Diff 效能。
静态提升:直接剔除比对对象
编译器在构建阶段就识别出完全不依赖响应式数据的节点(如 <p>欢迎使用</p>、无绑定属性的 <div class="header">),将其提取为常量 VNode,并缓存在 render 函数外部。运行时每次重新渲染,都复用同一引用。
<ul>
<li>避免重复创建 vnode 对象,减少内存分配和 GC 压力</li>
<li>该节点及其整个子树都不进入新旧 VNode 树的 diff 路径</li>
<li>连续多个静态节点(≥10 个)还会被合并为字符串节点,进一步压缩虚拟 DOM 规模</li>
</ul>
<h3>Patch Flags:精准锁定更新字段</h3>
<p>对未被提升的动态节点,编译器按更新类型打上位掩码标记,例如 <code>TEXT = 1、CLASS = 2、PROPS = 8。运行时 diff 只检查这些标记对应的具体字段,其余全部跳过。
-
<h2 :class="cls">{{ title }}</h2>会被标记为3(1 | 2),diff 仅比对文本内容和 class 属性 - 标记是编译期生成的常量,运行时零计算成本
- 没有 Patch Flags,静态提升后的剩余节点仍需全量比对;没有静态提升,Patch Flags 就得在一堆重复 vnode 中徒劳定位
Block Tree:组织动态更新单元
Vue3 把带 Patch Flag 的动态节点聚合成 Block(块),每个 Block 是一个最小可追踪更新单元。diff 过程只深入 Block 内部,Block 外的静态兄弟节点完全不参与遍历。
- 形成“跳过整块 → 定位节点 → 精比字段”的三级过滤链
- 中大型页面中静态节点常占 60% 以上,三者协同可使实际参与 diff 的节点数下降三分之二
- 首屏白屏时间减少 300ms+,列表滚动、表单交互等高频场景响应更及时
实际性能收益不是叠加,而是乘法效应
单独看,静态提升省的是 vnode 创建开销,Patch Flags 省的是比对逻辑,Block 省的是遍历路径。但三者串联后,运行时不再有“大量重复对象 + 全量树遍历 + 深度属性比对”这三重负担:
- 低端设备上 DOM 操作频次显著下降,重排重绘更少
- 组件更新从 O(n) 降为 O(m),其中 m 是真实动态节点数,远小于模板总节点数 n
- 在电商详情页、后台管理表格等典型场景中,帧率稳定性与交互吞吐量明显提升











