vue模板编译本质是将html模板字符串转为返回虚拟dom的渲染函数,分三步:解析成ast树、优化标记静态内容与补丁标志、生成可执行render函数代码。

Vue.js 模板编译过程本质是把我们写的 HTML 模板字符串,变成一个能返回虚拟 DOM 的 JavaScript 渲染函数。整个过程分三步走:解析出结构、优化运行效率、生成可执行代码——环环相扣,缺一不可。
解析:把模板转成 AST 树
这一步不做任何逻辑判断,纯“翻译”。Vue 读取 <template></template> 里的字符串,用状态机+正则的方式逐段识别:
- 遇到
<div> 就建一个 ELEMENT 节点,记录 tag 名、属性列表(如 <code>v-if="show")、子节点位置 - 碰到
{{ msg }}就生成 INTERPOLATION 节点,把表达式内容存进expression字段 - 纯文本如
Hello归为 TEXT 节点,标记static: true(若不含插值) - 靠节点栈维护嵌套关系,确保
<ul><li></ul>这类结构父子层级不乱 - 标记
static:整段没绑定响应式数据的节点(比如<p>欢迎使用 Vue</p>),运行时可跳过 diff - 标记
staticRoot:整个子树都是静态的根节点,后续 patch 可整块复用 - 打 PatchFlag:对动态部分分类标注,比如
TEXT(仅文本变)、PROPS(仅属性变),让运行时知道该更新哪一块 - 提取 v-if/v-for 逻辑:把条件分支、循环参数提前结构化,避免渲染函数里重复解析
- 递归遍历节点,对每个 ELEMENT 调用
_c('div', ...),TEXT 节点转成_v('xxx'),插值转成_s(expression) - 把 v-bind、@click 等语法,转成 props 对象或事件监听器配置项
- 静态节点单独生成
staticRenderFns,运行时缓存复用 - 最终产出一个函数体字符串,包裹在
with(this){return ...}或箭头函数中,导出为组件的render选项
输出是一个 JavaScript 对象树,每个节点带 type、tag、children 等字段,不执行、不求值,只忠实反映模板结构。
优化:标记静态内容,减少运行时开销
AST 生成后,Vue 会遍历它,做语义增强和性能预判:
这个阶段不改结构,只加元信息——所有标记都服务于后续 render 函数的轻量化执行。
生成:拼出最终的 render 函数字符串
最后一步是把优化后的 AST,“翻译”成浏览器能直接执行的 JS 代码:
生成结果不是立即执行,而是作为模块的一部分被 import、实例化、调用——真正干活的是运行时的渲染系统。











