vue 3 编译器是一套以优化为目标的静态分析流水线,包含静态节点提升、patch flags、block树结构和事件处理器缓存四大机制。

Vue 3 编译器不是“把模板转成 render 函数”就结束了,它是一套有明确优化目标的静态分析流水线。核心思路很直接:在编译阶段尽可能识别出哪些内容是静态的、哪些是动态的、哪些更新逻辑可以提前固化,从而大幅减少运行时的判断和计算。
静态节点提升(Hoist Static)
编译器会扫描整个模板,把完全不依赖响应式数据的节点(比如纯文本、无绑定属性的标签)提取出来,生成为模块级常量。这些节点在组件多次重渲染时复用,无需重复创建 VNode。
- 例如
<footer>Copyright 2023</footer>会被编译为const _hoisted_1 = createStaticVNode("...") - 提升后,render 函数只关注动态部分,AST 层级变浅,diff 范围缩小
- 默认开启,可通过
compilerOptions.hoistStatic: false关闭(一般不建议)
Patch Flags 动态标记
这是 Vue 3 渲染性能跃升的关键。编译器为每个动态 vnode 添加二进制位标记(如 1 /* TEXT */、2 /* CLASS */),告诉运行时“这个节点哪些部分会变”。patch 阶段据此跳过无关更新,避免全量 diff。
分析 Vue 3 Composition API 使用情况——审计响应式模式、可组合函数设计、ref 与 reactive 的选择、计算属性、watcher 使用及组件……
- 常见标志:TEXT(文本变化)、CLASS(class 变化)、STYLE(style 变化)、PROPS(非 class/style 的属性)、FULL_PROPS(需全量比对)等
- 比如
<p :class="cls">{{ msg }}</p>会同时打上 CLASS 和 TEXT 标志 - 标记由编译器自动推导,开发者无需手动干预,但理解它有助于写出更易被优化的模板
Block 树结构与动态块(Dynamic Block)
Vue 3 放弃了 Vue 2 的全量 VDOM 树,转而构建以“Block”为单位的嵌套结构。每个 Block 是一个最小动态作用域,内部只包含真正可能变化的节点。这样 patch 时只需遍历 Block,跳过整棵静态子树。
- Block 由
createBlock()创建,包裹一组 vnode;静态提升后的节点则用createVNode()直接挂载 - 一个
v-if分支、一个v-for列表、甚至一个带动态属性的<div> 都可能成为独立 Block<li>Block 内部的动态节点再通过 Patch Flags 细粒度控制更新路径,形成“块级 + 位级”双重优化</li> <h3>事件处理器缓存(Cache Handlers)</h3> <p>对于内联事件函数(如 <code>@click="handleClick"),编译器默认会将其包装并缓存,避免每次渲染都新建函数实例,减少内存分配与 GC 压力。- 未启用缓存:
createVNode('button', { onClick: _ctx.handleClick }) - 启用缓存:
createVNode('button', { onClick: _cache[0] || (_cache[0] = $event => _ctx.handleClick($event)) }) - 可通过
compilerOptions.cacheHandlers: true显式开启(Vue CLI/Vite 默认已启用) - 注意:仅对简单内联调用有效;含闭包或复杂表达式的事件仍需手动提取为方法
- 未启用缓存:









