patchflag 是 vue 编译器为动态节点标记的整数标志,用于运行时精准识别需更新的属性类型(如 props、class、文本等),跳过静态内容比对,实现靶向 diff。

Vue.js 的 PatchFlag 是编译器与运行时协同优化的核心设计之一,它让虚拟 DOM 的 diff 过程不再“全量扫描”,而是精准定位需要更新的节点,实现真正的靶向更新。
PatchFlag 是什么?
PatchFlag 是 Vue 编译器在生成虚拟 DOM(VNode)时,为动态节点打上的整数标记。它编码了该节点有哪些类型的动态性(比如文本变化、class 变化、props 变化等),运行时 patch 阶段可直接读取该标志,跳过静态内容或无需比对的部分。
例如:
h('div', { class: 'static', id: ctx.id }, ctx.msg)
编译后,id 和 msg 对应的 VNode 会被分别标记 PATCH_FLAG_PROPS(1 PATCH_FLAG_TEXT(1
如何辅助编译器做靶向决策?
编译器不是盲目生成 flag,而是基于模板语法的语义分析,精确判断每个动态绑定的“变更维度”:
分析 Vue 3 Composition API 使用情况——审计响应式模式、可组合函数设计、ref 与 reactive 的选择、计算属性、watcher 使用及组件……
- 仅
{{ msg }}→ 打PATCH_FLAG_TEXT,运行时只比对 textContent - 绑定
:class="{ active: isActive }"→ 打PATCH_FLAG_CLASS,patch 时只更新 className -
v-if或v-for生成的子树 → 打PATCH_FLAG_BLOCK,启用块级 diff 算法,跳过内部静态节点遍历 - 多个响应式 prop 同时存在(如
:id="id" :title="title")→ 合并为PATCH_FLAG_PROPS | PATCH_FLAG_DYNAMIC_SLOTS等位或结果
运行时如何“靶向”执行更新?
当 patchElement 被调用时,会根据 VNode 的 patchFlag 值快速分支,避免通用 diff 的冗余逻辑:
- flag 包含
PATCH_FLAG_TEXT→ 直接el.textContent = next.children,不走 children diff - flag 包含
PATCH_FLAG_CLASS→ 调用patchClass(el, prev, next),不检查 style、attrs、events - flag 为 0(无动态性)→ 完全跳过该节点的 props/children 更新,连属性键名遍历都省了
- 结合
dynamicProps数组(编译器提取出真正响应式的 prop 名),还能按需更新具体属性,而非遍历全部 attrs
为什么说这是“编译时 + 运行时”协作的结果?
PatchFlag 的价值不在运行时单独存在,而在于它把原本必须在运行时推断的更新意图,提前固化到 VNode 结构中:
- 编译器知道
{{ count + 1 }}只影响文本,所以只标 TEXT;但若写成v-html="html",就标PATCH_FLAG_HTML - 没有 PatchFlag,运行时只能保守地执行完整 props diff + children diff,成本随模板复杂度线性上升
- 有了 PatchFlag,90%+ 的更新操作可降维到单属性赋值级别,性能提升肉眼可见,尤其在长列表或高频更新场景
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!










