Vue.js 模板编译本质是将 HTML 模板字符串经解析(生成含指令、插值等信息的 AST)、优化(标记静态节点以跳过 diff)和代码生成(输出含 _c/_v 调用的 render 函数)三步,最终产出返回 VNode 的 JavaScript 渲染函数。

Vue.js 的模板编译本质是把声明式的 HTML 模板字符串,经过解析、优化和代码生成三步,最终转为可执行的 JavaScript 渲染函数(render function)。这个函数返回虚拟节点(VNode),供 Vue 运行时用来构建和更新真实 DOM。
模板解析:生成抽象语法树(AST)
编译器第一步是将模板字符串(如 <div v-if="show">{{ msg }}</div>)通过正则与状态机结合的方式进行词法分析和语法分析,产出一个嵌套结构的 AST 对象。这个 AST 节点包含类型(type)、标签名(tag)、属性列表(attrsList)、指令(directives)、子节点(children)等字段。
- 文本插值
{{ msg }}会被标记为text类型节点,并记录表达式内容 - v-if、v-for 等指令会作为
directives数组项附加到对应元素节点上 - 静态内容(如纯文本或无绑定的 HTML)会被打上
static标记,便于后续优化
AST 优化:标记静态节点与提升性能
优化阶段不改变 AST 结构,而是遍历它,为可判定的静态子树打上 static 和 staticRoot 标志。静态节点指在运行时不会变化的节点(不含响应式绑定、指令、插槽等)。
将一个或多个视频上传至YouTube。当用户想“上传到YouTube”“发YouTube”“批量上传”“upload to YouTube”“post videos to YouTube”或发布到YouTube时使用此技能。
- 静态根节点(
staticRoot: true)表示整个子树都静态,可在首次渲染后跳过 diff - 优化后的 AST 会减少运行时 VNode 创建开销,尤其对大量静态内容的模板效果明显
- 注意:含
v-if、v-for或插槽的节点无法被标记为静态,即使其内部内容看起来“不变”
代码生成:输出可执行的 render 函数字符串
最后一步是将优化后的 AST 转为字符串形式的 JavaScript 函数体,包裹在 with(this){return ...} 作用域中(非 strict 模式),最终通过 new Function() 编译成函数对象。
立即学习“前端免费学习笔记(深入)”;
-
_c是createElement的别名,用于创建普通 VNode;_v处理文本;_e创建空 VNode - v-if 编译为三元表达式:
show ? _c('div', [...]) : _e() - v-for 编译为
_l(即renderList)调用,返回数组形式的 VNode 列表 - 用户写的
scopedSlots、ref、key等都会被映射为对应参数传入_c
开发中可观察编译结果的几种方式
理解编译过程最直接的方式是查看实际产出的 render 函数:
- 使用
vue-template-compiler包的compile方法手动编译模板 - 在 Vue Devtools 中查看组件的
$options.render属性(需非生产模式) - 在 SFC(.vue 文件)中启用
compilerOptions.preserveWhitespace: false观察空格压缩效果 - Vue CLI 项目可通过
vue inspect --mode development查看 loader 配置与编译行为

















