PatchFlags是Vue3编译器在构建阶段写入VNode的“更新说明书”,非运行时推测;它通过-1(STATIC)、1(TEXT)、4(CLASS)等位掩码标记动态部分,运行时按位与精准比对,跳过静态内容与未改动字段,实现靶向更新,相比Vue2全量diff显著提升性能。

动态节点标记(Patch Flags)不是运行时猜出来的,是 Vue3 编译器在构建阶段就写进虚拟节点(VNode)里的“更新说明书”。它让 Diff 算法跳过大量静态内容,只聚焦真正可能变化的部分,从而把原本的全量比对变成靶向更新。
它怎么标记?编译时就定死
Vue3 模板一被解析,编译器立刻分析每个节点:
-
纯静态内容(比如
<p>欢迎光临</p>)→ 标记为PATCH_FLAG.STATIC(值为 -1),后续 diff 完全跳过,连子节点都不进 -
带插值的文本(比如
<p>{{ message }}</p>)→ 标记为PATCH_FLAG.TEXT(值为 1) -
动态 class(比如
<div :class="cls"></div>)→ 标记为PATCH_FLAG.CLASS(值为 4) -
多个动态项共存(比如
<div :class="cls">{{ msg }})→ 标记为CLASS | TEXT(即 4 | 1 = 5),表示只需检查 class 和文本两处
它怎么加速 Diff?按位与快速决策
运行时触发更新时,patch 函数拿到节点的 patchFlag,直接用位运算判断该做什么:
- 遇到
-1→ 不比较、不递归、直接复用整棵子树 - 遇到
flag & TEXT成立 → 只比对node.children文本,其他字段(props、style、事件等)一律跳过 - 遇到
flag & CLASS成立 → 只比对node.props.class,其余 props 不看 - 没匹配到任何 flag 的字段 → 连比都不比,省下所有计算和内存访问
它和 Vue2 的区别在哪?从“全查”到“不查”
Vue2 的 Diff 是运行时逐节点遍历,不管节点有没有变,都走一遍属性比对逻辑;Vue3 把判断提前到编译期,结果就是:
- 静态节点:不进入 diff 主流程,零开销
- 动态节点:只比对标记出的字段,避免无效属性扫描
- 列表更新:配合 Block Tree 收集动态节点,进一步缩小 diff 范围
- 整体效果:大型组件中,diff 时间可减少 30%~50%,尤其在低性能设备上感知明显
它不改变你写模板的方式,却悄悄把 Diff 从地毯式搜索变成了精准导航。








