shapeflags 和 patchflags 是 vue 3 中两个正交的位标志系统:前者标识 vnode 静态结构类型(如 element=1、stateful_component=4),后者标记动态更新字段(如 text=1、class=2);二者定义分离、比特位不重叠,不可混用。

“PatchFlags.SHAPE_FLAG”这个写法本身并不存在——这是常见的概念混淆。Vue 3 中没有 PatchFlags.SHAPE_FLAG 这个枚举项,ShapeFlags 和 PatchFlags 是两个完全独立、职责分明的位标志系统,分别定义在不同模块中,不能混用或嵌套引用。
ShapeFlags 是什么?静态身份标识
ShapeFlags 描述的是 VNode 的结构本质:它是什么类型的节点、子节点以何种形式组织、是否具备容器语义等。这些信息在 VNode 创建时就确定,整个生命周期不变。
- ELEMENT(值为 1):普通 HTML 元素,如
<div> <li>STATEFUL_COMPONENT(值为 4):有状态组件(含 setup / data / 生命周期)</li> <li>FUNCTIONAL_COMPONENT(值为 2):纯函数式组件</li> <li>TEXT_CHILDREN(值为 8):children 是字符串</li> <li>ARRAY_CHILDREN(值为 16):children 是 VNode 数组</li> <li>FRAGMENT / TELEPORT / SUSPENSE(各占一个独立比特位):高阶容器节点</li> <p>它们通过位或(<code>|)组合。例如一个返回数组的有状态组件,其shapeFlag = STATEFUL_COMPONENT | ARRAY_CHILDREN = 4 | 16 = 20(二进制00010100)。PatchFlags 是什么?动态更新线索
PatchFlags 描述的是 VNode 中哪些部分绑定了动态值,由模板编译器在编译阶段生成,用于运行时跳过静态内容、只更新真正变化的字段。
- TEXT(1):textContent 动态绑定(如
{{ msg }}) - CLASS(2):class 属性动态绑定
- STYLE(4):style 属性动态绑定
- PROPS(8):除 class/style 外的其他 props 动态绑定
- FULL_PROPS(16):props 完全动态(如
v-bind="obj") - KEYED_FRAGMENT(128):带 key 的多根节点片段
比如
<div :class="cls" :style="sty">{{ text }},它的 <code>patchFlag = CLASS | STYLE | TEXT = 2 | 4 | 1 = 7,patch 阶段就只比对这三项,其余属性直接复用。为什么二者不能混用?分工不可替代
ShapeFlags 解决“这是什么”,PatchFlags 解决“哪里要改”。它们作用于渲染流程的不同阶段:
- createVNode 阶段:根据节点类型(如组件、元素)计算并设置
shapeFlag;同时编译器注入patchFlag - patch 阶段:先用
shapeFlag & ELEMENT快速分发到processElement;进入后,再用patchFlag & TEXT判断是否需更新文本 - 若强行把 ShapeFlags 当 PatchFlags 用(如
patchFlag & STATEFUL_COMPONENT),结果恒为 0——因为它们的比特位不重叠,逻辑上无意义
怎么查真实定义?看源码位置
两者都定义在
@vue/shared包中,但文件分离清晰:-
packages/shared/src/shapeFlags.ts:导出enum ShapeFlags,含 ELEMENT、COMPONENT 等 -
packages/shared/src/patchFlags.ts:导出enum PatchFlags,含 TEXT、CLASS、DYNAMIC_SLOTS 等 - 它们互不 import,也不共享常量名,是两套正交的位域设计
- TEXT(1):textContent 动态绑定(如











