靶向更新是Vue3通过编译时标记patchFlags(如TEXT=1、CLASS=2)并运行时按位运算精准定位需更新字段,跳过静态节点与未改动属性,结合Block Tree批量处理dynamicChildren,实现确定性、零冗余的高效DOM更新。
“靶向更新”是 Vue3 渲染机制的核心优化策略,它不是泛泛地比对整个 VNode 树,而是只聚焦于真正变化的节点及其具体字段,跳过所有静态或未改动的部分。本质是编译时标记 + 运行时按位分流,让 patch 流程从“猜哪里变了”变成“直接知道该更新什么”。
Vue3 编译器在解析模板时,会逐个分析节点是否依赖响应式数据:
<h1>标题</h1>)不打任何标记,后续永不参与 diff<p>{{ msg }}</p>)被打上 PATCH_TEXT = 1
<div :class="cls">)被打上 PATCH_CLASS = 2
<div :class="cls" :style="s" @click="h">{{ msg }}</div>)标记为 1 | 2 | 8 = 11(二进制 1011)这个数字会被写入 VNode 的 patchFlag 字段,成为运行时决策的唯一依据。
当响应式数据变更触发重新 render 后,新旧 VNode 进入 patch 阶段。此时不再遍历 props 或 children 对象,而是直接查 flag:
立即学习“前端免费学习笔记(深入)”;
newVNode.patchFlag & TEXT 为真 → 仅比对 newVNode.children 和 oldVNode.children 的文本内容newVNode.patchFlag & CLASS 为真 → 仅浅比较 newVNode.props.class 与 oldVNode.props.class
style、key、ref)完全跳过,连属性名都不读取整个过程不依赖 for-in、Object.keys 或深度递归,一次按位与操作即可定位行为分支,耗时在纳秒级。
Vue3 不再把 VNode 当作孤立对象处理,而是构建了 Block(块)结构:
patchFlag 的动态节点收集到 Block 的 dynamicChildren 数组中dynamicChildren,忽略 Block 内所有静态子节点这相当于把“哪些节点要动”提前打包成清单,运行时无需现场判断——既减少判断开销,又提升 cache 局部性。
Vue2 的 patch 是通用型:不管节点有没有变,都得走一遍 props diff、children diff、事件比对等完整流程;而 Vue3 的靶向更新是契约型:编译阶段已签好“本次只改文本和 class”,运行时就严格履约,不做一丁点多余动作。
这不是算法层面的改进,而是用编译期信息把不确定性转化为确定性——让 CPU 少做选择,多做执行。