patchflag 的核心作用是让 vue 渲染器跳过静态内容,只聚焦真正可能变化的部分,把“全量比对”变成“按需更新”;它由编译器在生成 createvnode 时写死为位掩码数字(如 text=1、class=2),运行时通过按位与精准执行对应 patch 逻辑,避免冗余 diff。

PatchFlag 的核心作用是让 Vue 渲染器跳过静态内容,只聚焦真正可能变化的部分,把“全量比对”变成“按需更新”。它不是运行时猜出来的,而是在编译阶段就由模板结构决定的——编译器一看见动态绑定,就立刻打上对应数字标记,运行时 patch 函数拿到这个数字,直接走专用逻辑。
它怎么知道该比什么?
每个 PatchFlag 值对应一类变更类型。比如值为 1 表示只有文本变了,值为 4(即 CLASS)表示只更新 class 字符串,值为 8(PROPS)表示要检查部分属性。这些数字是位运算组合的,可以同时表达多种动态性,比如 4 | 8 就是 class + 部分 props 都要更新。
- 遇到
PATCH_FLAG_TEXT:直接改el.textContent,不进 children diff 流程 - 遇到
PATCH_FLAG_CLASS:调用patchClass(),只处理 className,style、attrs、事件全都不看 - flag 为 0:整个节点完全跳过 props 和 children 更新,连属性键名遍历都省了
为什么能省掉大量计算?
没有 PatchFlag 时,Vue 必须对每个 VNode 的所有属性和子节点做通用 diff —— 即便那些内容根本没变。有了它,运行时不再需要逐个判断“这个 class 变了吗?那个 style 变了吗?这些 props 里哪些动了?”,而是直接根据 flag 分支执行最简路径。
- 静态节点(如纯文字
<p>欢迎</p>)会被提升为常量,渲染时直接复用,不重新创建 - 动态绑定越精准,flag 越细粒度,比如
:class="{a: isA}"打的是CLASS,而:class="cls + ' b'"打的是更宽泛的PATCHED,后者更新开销更大 - 多个响应式 prop 同时存在时,编译器会合并成一个 flag,再配合
dynamicProps数组,只更新实际变动的那几个 key
它依赖编译器和运行时的紧密配合
PatchFlag 不是运行时自己推断出来的,而是编译器在生成 render 函数时就写死在 createVNode() 调用里的第三个参数。例如:createVNode("div", { class: _ctx.cls }, "hello", 4) —— 最后的 4 就是告诉运行时:“只管 class,别的别碰”。
- 编译器负责语义分析:{{ msg }} → TEXT;
:class="..."→ CLASS;v-if包裹的节点 → BLOCK - 运行时负责快速路由:看到 flag 就跳转到对应 patch 方法,避免通用 diff 的层层判断
- 这种分工把“该更新什么”的决策提前固化,让高频更新场景(比如列表滚动、表单联动)的 diff 成本大幅下降
不复杂但容易忽略:它的加速效果不是靠某一行代码,而是整套编译+运行时协同机制共同作用的结果。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!










