vue.js 3 编译器自动将纯静态内容(如纯文本、无指令静态元素)提升为常量 vnode 以减少创建开销;被提升节点在 render 外定义并带 -1 标志,render 内直接引用;v-memo 可辅助优化伪静态场景,但 hoisting 不跳过 diff。

Vue.js 3 的编译器会对模板中完全静态的内容自动执行 Hoisting(提升),将其提前创建为常量 VNode,避免每次渲染重复构造。这直接减少了 VNode 创建开销,尤其在列表、高频更新组件中效果明显——但前提是内容必须真正静态,且需理解其生效边界。
哪些内容会被 Hoist?
只有编译期可确定、运行时绝不变化的节点才会被提升:
- 纯文本节点:
{{ "Hello" }}或直接写死的Hello World - 静态元素(无指令、无插值、无动态属性):
<div><span>Loading...</span></div> - 静态组件(仅含静态 prop,且组件本身被标记为
__static或满足条件) - 不被提升的情况:
<div :class="cls">{{ msg }}</div>(含响应式绑定)、<p v-if="show">...</p>(含指令)、<mycomp :msg="dynamicMsg"></mycomp>(prop 动态)
如何验证 Hoisting 是否生效?
查看编译后的 render 函数输出(可通过 vue/compiler-sfc 或 SFC Playground):
将一个或多个视频上传至YouTube。当用户想“上传到YouTube”“发YouTube”“批量上传”“upload to YouTube”“post videos to YouTube”或发布到YouTube时使用此技能。
- 被提升的节点会出现在 render 函数外部,形如
const _hoisted_1 = /*#__PURE__*/ createVNode("span", null, "Static Text", -1) -
-1表示PATCH_FLAG_TEXT,标志该 VNode 是静态且不可补丁更新的 - render 内部则直接引用
_hoisted_1,而非调用createVNode
主动优化:用 v-memo + Hoisting 组合应对“伪静态”场景
有些内容看似静态,实则依赖 props 或 setup 中的局部变量(非响应式),编译器无法识别。此时可手动拆分:
- 将稳定子树提取为计算属性或顶层常量(确保不依赖响应式状态)
- 对含少量动态插槽的静态容器,用
v-memo缓存整个 VNode 子树:<div v-memo="[props.id]"> <header>User Profile</header><slot></slot> </div> - 避免在静态区域混用响应式表达式,例如把
{{ user.name }}和静态文案拆到不同元素中,让纯静态部分独立成节点
注意边界:Hoisting 不等于跳过 Diff
被提升的 VNode 仍参与挂载和卸载流程,只是省去了每次 createVNode 调用及内部属性合并逻辑。它不会跳过父组件的 patch 过程,也不会影响响应式更新链路。若父节点因响应式变化需要重绘,被 hoist 的子节点依然会被复用(因其是不可变常量),这是性能收益的核心。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!










