vue.js编译器在编译阶段通过静态分析识别完全不依赖响应式数据的节点,满足纯文本/静态元素、无指令/动态绑定/插值、子节点全静态等条件即标记为静态,随后提升为常量vnode复用。

Vue.js 编译器通过静态分析在编译阶段识别出完全不依赖响应式数据的模板内容,并将其提取为常量,避免每次渲染重复创建 vnode,从而实现静态内容复用。这不是运行时判断,而是一次确定性的代码生成优化。
静态节点如何被识别
编译器在 transform 阶段递归检查每个 AST 节点,只有同时满足以下条件才会标记为静态(isStatic: true):
- 节点类型是纯文本、注释或静态元素(如 )
- 元素不含任何指令(v-if、v-for、@click 等)、动态属性绑定(:class、:style)或事件监听
- 不包含插值表达式({{ }}),除非在 v-pre 下
- 所有子节点也必须满足上述全部条件(递归判定)
静态提升(hoistStatic)的具体过程
一旦节点被判定为静态,编译器会执行提升操作,核心步骤包括:
- 调用 getConstantType 函数评估节点常量级别,确认是否可达 ConstantTypes.CAN_CACHE
- 为该节点添加 PatchFlags.CACHED 标记
- 将整个静态子树生成为一个独立的 createVNode 调用,并提升到 render 函数外部(如 const hoisted1 = h('h1', {}, '标题'))
- 后续所有 re-render 中直接复用该 vnode 实例,跳过创建、props 合并与子节点遍历
静态属性的提取逻辑
HTML 属性层面也有类似机制,称为“静态 props 提取”,由 transformHoist 插件完成:
- 仅当属性值是纯字符串(class="btn")、原生布尔属性(disabled)、或静态绑定(:class="'fixed'")时才被识别
- 禁止混用:class="a" :class="b" 会让整个 class 属性判为动态
- v-bind 批量绑定中只要一个值含变量,整组失效
- 提取后的静态 props 直接作为 createVNode 的第二个参数传入,脱离响应式上下文和 patch 流程
为什么不能靠组件实例来“静态化”
需要特别注意:静态提升只作用于 DOM 节点,不是组件实例。即使一个组件只接收字面量 prop(如
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











