isstatic 是编译期静态标记而非运行时开关,vue 在 transform 阶段递归判定节点是否纯静态(无指令、无插值、子节点全静态),满足则标记 isstatic: true,触发静态提升以复用 vnode、减少渲染开销。

直接用 isStatic 属性本身并不能“优化重复渲染”,它只是一个**判定标识**,真正起效的是框架(如 Vue)基于这个标识做的编译与运行时优化。关键在于理解它的作用位置和触发条件——它出现在模板编译阶段,用于识别哪些节点可被提升、跳过 diff 或缓存。
明确 isStatic 是编译期标记,不是运行时开关
Vue 编译器在 transform 阶段会调用 isStatic(node) 函数判断节点是否静态。只有满足以下全部条件,才会被打上 isStatic: true 标记:
- 节点类型是纯文本(Text)、注释(Comment)或静态元素(Element)
- 元素没有动态属性:比如不含
v-if、v-for、:class动态绑定、@click事件等指令 - 所有子节点也必须是静态的(递归判定)
- 不包含插值表达式(
{{ }}),除非该表达式被显式标记为静态(如v-pre下的内容)
主动配合 isStatic 的三种实用写法
你无法手动设置 isStatic,但可以通过结构设计让编译器更容易识别并标记它:
-
用
v-pre包裹确定不变的区块:比如页脚版权、文档说明、HTML 片段示例。它强制跳过编译,天然视为静态,避免 AST 解析开销 - 把重复静态内容抽成独立组件或片段:例如通用标题栏、空状态提示、图标 SVG 内联模板。组件模板若全静态,整个子树会被整体提升复用
-
避免在静态区域混入响应式逻辑:比如不要在一段纯文字里加一个
v-show="false"—— 即使条件恒假,也会让节点失去isStatic标记,导致无法提升
静态提升(hoistStatic)带来的真实收益
当节点被正确标记为 isStatic: true 后,Vue 3 编译器会在生成 render 函数时执行静态提升:
- 将静态 vnode 提取到函数外部,只创建一次(如
const hoisted1 = h('div', [...])) - 后续每次 re-render,直接复用已创建的 vnode 对象,跳过创建、props 合并、子节点遍历等流程
- 减少内存分配与 GC 压力,尤其在高频更新或长列表场景下效果明显
别误用 v-once 替代 isStatic 判定
v-once 和 isStatic 目标相似但机制不同:
-
v-once是运行时指令,告诉 Vue “这次渲染完就冻结”,适用于含响应式数据但只渲染一次的场景(如首次欢迎语) -
isStatic是编译期结果,代表“从始至终都不变”,适用于完全无数据依赖的结构(如<h2>用户协议</h2>) - 混用可能适得其反:给一个本可静态提升的节点加
v-once,反而干扰编译器优化路径










