静态提升是vue 3编译阶段将纯静态节点(无插值、指令、动态属性,子树全静态)提取为顶层常量vnode并复用的优化,减少运行时vnode创建、内存分配与diff负担。

静态提升(Static Hoisting)是 Vue 3 编译器在构建阶段自动完成的一项关键优化,它把模板中“完全不变”的节点提前创建为常量 VNode 并缓存,运行时直接复用,从而跳过重复的 VNode 构造、减少内存分配、降低 diff 比对负担。
哪些节点会被提升?
不是“看起来静态”就行,必须满足严格判定条件:
- 节点类型只能是普通 HTML 元素(如
<div>、<code><p></p>)或纯文本,不能是组件、v-for、v-if、v-slot等动态容器 - 节点内不含任何插值(
{{ }})、指令(v-)、事件绑定(@click)或动态属性(:id) - 所有属性值必须是字符串字面量:比如
class="btn"✅,但:class="cls"❌;style="color:red"✅,而:style="{ color }"❌ - 整棵子树都得静态:哪怕一个子节点含
{{ msg }},其父节点就整体失去提升资格 - 首屏渲染多一次对象创建,但后续所有更新都省掉这部分开销
- VNode 创建减少 → 内存分配减少 → GC 触发频率下降
- diff 跳过静态节点 → 比对路径大幅缩短,尤其对长列表、复杂页脚等场景效果显著
- 配合 Block Tree,patch 过程可跳过整块静态区域,效率进一步提升
- 把确定不变的内容写得更“干净”:能用
class="xxx"就别写:class="['xxx']" - 避免在静态标签里混用动态绑定,比如
<div class="logo" :title="tooltip"> → 整个 div 就不再是静态节点 <li>不要用 <code>v-if="true"或v-show="true"包裹静态内容,这会让结构失去稳定性 - 连续多个静态节点(≥10 个)会被自动字符串化合并,适当组织 HTML 结构有助于提升效率
它是怎么工作的?
编译器扫描 AST,在生成 render 函数前就把符合条件的节点抽出来,定义在 setup 外部:
const _hoisted_1 = /*#__PURE__*/_createVNode("h1", null, "欢迎页", -1)
render 函数中不再调用 _createVNode 创建它,而是直接引用 _hoisted_1。它的 PatchFlag 被设为 -1(HOISTED),diff 阶段完全跳过比对。
即使整个标签因含动态内容无法整体提升,它的静态属性仍可被单独提取:
<div :id="dynamicId" class="container" data-role="main">{{ content }}</div>
编译器会提取出 { class: "container", "data-role": "main" } 并缓存为 _hoisted_1,渲染时通过 _mergeProps({ id: _ctx.dynamicId }, _hoisted_1) 合并使用,避免每次构造新 props 对象。
为什么能真正提速?
核心在于把运行时开销前置到编译期解决:
你可以做点什么?
静态提升全自动,无需手动开启,但写法会影响效果:











