vue 3 的“靶向更新”指编译器自动生成 patchflag 标记动态节点、运行时 patch 函数据此跳过静态比对,实现精准高效 dom 更新,无需手动追踪数据。

Vue 3 的“靶向更新”并非一个官方术语,而是开发者对 PatchFlag 机制下高效、精准 DOM 更新行为的形象说法。它本质是编译阶段自动标记动态节点 + 运行时跳过静态内容比对,从而缩小 diff 范围、提升更新性能。真正起作用的是 编译器生成的 PatchFlag + 运行时 patch 算法协同优化,不是靠手动“追踪某个数据”实现的。
PatchFlag 是什么?编译器埋下的“更新线索”
PatchFlag 是 Vue 3 编译器(@vue/compiler-dom)在模板编译阶段,根据节点内容是否含动态绑定,自动为 VNode 打上的数字标记。它告诉 runtime:“这个节点哪些部分会变,其他部分不用比”。比如:
-
1 /* TEXT */:只有子文本内容会响应式更新(如
{{ msg }}) -
2 /* CLASS */:只有 class 绑定会更新(如
:class="cls") - 8 /* PROPS */:有非 class/style 的动态 prop(且不含 v-on),需按 key 更新 props
-
32 /* HYDRATE_EVENTS */:含内联事件监听器(如
@click="handler")
这些 flag 是整数,支持位运算组合(如 1 | 2 表示文本+class都可能变)。你无需手写 flag,Vue CLI 或 Vite 默认已启用编译优化。
如何让 PatchFlag 生效?写模板就有用
PatchFlag 完全自动生效,关键在于写符合优化条件的模板。以下写法能触发有效 flag:
- 用
v-if/v-for包裹的节点,内部动态绑定会被单独标记 - 避免在同一个元素上混写大量静态属性和动态绑定(如
<div id="static" :class="a" :style="b"> → class 和 style 会被分别标记)<li>使用 <code><template v-if></template>替代无意义的包裹 div,减少冗余节点干扰 flag 分布 - 静态内容尽量不加响应式变量,例如
<p>用户名:{{ user.name }}</p><div class="aritcle_card flexRow artxards"> <div class="artcardd flexRow"> <a class="aritcle_card_img" rel="nofollow" href="/xiazai/skill5039" title="check-vue-style"><img src="https://img.php.cn/upload/skill/000/000/081/179032142844293.jpg" alt="check-vue-style" onerror="this.onerror='';this.src='/static/lhimages/moren/morentu.png'" ></a> <div class="aritcle_card_info flexColumn"> <a rel="nofollow" href="/xiazai/skill5039" title="check-vue-style" class="overflowclass">check-vue-style</a> <p class="overflowclass">检查 .vue 单文件组件的 CSS 规范问题并给出提示,适用于样式检查、CSS审查和 Vue 页面质量巡检。</p> </div> <a rel="nofollow" href="/xiazai/skill5039" title="check-vue-style" class="aritcle_card_btn flexRow flexcenter"><b></b><span>下载</span> </a> </div> </div>中 “用户名:” 是静态文本,仅user.name触发 TEXT flag - 若 flag > 0,跳过静态属性比对,只处理标记对应的部分(如 flag=2 就只更新 class,不碰 props、children)
- 若 flag = 0(或未设置),走传统全量 diff 流程(兼容旧写法或 SSR hydration 场景)
- 结合
dynamicChildren(编译生成的动态子节点数组),对 v-for 列表等场景进一步跳过稳定子项比对 - Vite 项目:在
vite.config.ts中临时开启build.sourcemap = true,然后在浏览器 Sources 面板找.vue?t=script对应的 JS,搜索createVNode - 或使用 Vue Template Explorer 粘贴模板,直接看编译结果中
createVNode(..., ..., PatchFlag)的第三个参数值 - 常见 flag 值含义可查 源码 constants(如
PATCHED,TEXT,CLASS)
反例:<div v-html="content"></div> 无法打 flag,整个节点被当作黑盒处理,更新时全量替换。
运行时怎么利用它?patch 函数自动识别
Vue 3 的核心更新函数 patch() 在对比新旧 VNode 时,会读取新节点的 patchFlag:
你不需要调用任何 API,只要用标准 Composition API 响应式数据(ref/reactive),触发 trigger 时,框架自动按 flag 最小化更新真实 DOM。
调试 PatchFlag:看编译输出最直观
想确认某段模板是否生成了预期 flag?可查看编译后的 render 函数:
例如模板 <h1 :class="cls">{{ title }}</h1> 通常生成 createVNode("h1", { class: cls }, title, 3) —— 3 = 1 | 2,即 TEXT + CLASS 同时变化。










