PatchFlags 是 Vue3 编译时标记的更新说明书,静态节点标为 -1 全跳过,动态节点按位与精准比对文本、class 等,相比 Vue2 全量 diff 显著提升性能。

“静态标记”(PatchFlags)是 Vue3 编译器在生成虚拟 DOM 节点(VNode)时,悄悄打上的“更新说明书”。它不改变模板写法,却让运行时的 Diff 过程一眼识别:哪些地方可能变、哪些地方绝不会变——该跳就跳,不比不查。
它不是运行时猜的,是编译时就定好的
Vue3 的模板在首次构建时就被编译器深度分析。比如这段模板:
欢迎光临 {{ message }}
编译器会立刻判断:
- 第一行
<p>欢迎光临</p>全是固定文本 → 标记为 PatchFlags.STATIC(值为 -1),后续 diff 完全跳过 - 第二行
<p>{{ message }}</p>文本会随数据变化 → 标记为 PatchFlags.TEXT(值为 1) - 外层
<div> 的 <code>:class是动态的 → 标记为 PatchFlags.CLASS(值为 2) - 而它的
class="header"是静态部分,不参与标记,也不进 diff 流程 - 遇到
patchFlag === -1(STATIC)→ 直接复用旧 VNode,连子节点都不进 - 遇到
patchFlag & PatchFlags.TEXT成立 → 只比对文本内容,跳过 class、style、props、事件等所有其他字段 - 遇到
patchFlag & PatchFlags.CLASS成立 → 只更新 class 属性,其余一概忽略 - 若
patchFlag === 0(无标记)→ 按传统方式全量比对(极少见,通常说明没走编译优化路径) - 哪怕只有 1 个文本变了,整个组件的全部子节点都要递归比对一遍
- 静态
<p>欢迎光临</p>每次都新建 VNode、再比对、再确认没变——纯属白忙 - 静态节点被提前“提出来”(hoistStatic),只创建一次,反复复用
- 每个动态节点自带小标签(PatchFlag),diff 函数扫一眼就知道“只改文字”或“只刷 class”
- 真正需要计算的,可能只是整棵树里几个叶子节点,其余全跳过
-
TEXT(1):仅文本插值变化,如
{{ msg }} -
CLASS(2):仅
:class绑定变化 -
STYLE(4):仅
:style绑定变化 -
PROPS(8):其他属性变化(需配合
dynamicProps列表限定范围) - STATIC(-1):彻底静态,diff 阶段直接跳过整棵子树
Diff 过程中,PatchFlags 怎么指挥跳过?
当 message 改变触发更新时,Vue 不会从头到尾遍历整个 div 树。它只看每个节点的 patchFlag 数字,然后按位与(&)快速判断该处理哪部分:
和 Vue2 对比,差别在哪?
Vue2 的 diff 是“宁可错杀,不可放过”:
Vue3 则像拿着清单干活:
常见 PatchFlag 类型速查
这些标记常以位运算组合出现(如 TEXT | CLASS = 1 | 2 = 3),表示该节点同时有文本和 class 动态性:

















