9 如何理解Vue中模板编译原理
Vue的编译过程就是将template转化为render函数的过程
- 解析生成AST树 将
template模板转化成AST语法树,使用大量的正则表达式对模板进行解析,遇到标签、文本的时候都会执行对应的钩子进行相关处理 - 标记优化 对静态语法做静态标记
markup(静态节点如div下有p标签内容不会变化)diff来做优化 静态节点跳过diff操作Vue的数据是响应式的,但其实模板中并不是所有的数据都是响应式的。有一些数据首次渲染后就不会再变化,对应的DOM也不会变化。那么优化过程就是深度遍历AST树,按照相关条件对树节点进行标记。这些被标记的节点(静态节点)我们就可以跳过对它们的比对,对运行时的模板起到很大的优化作用- 等待后续节点更新,如果是静态的,不会在比较
children了
- 代码生成 编译的最后一步是将优化后的
AST树转换为可执行的代码
回答范例
思路
- 引入
vue编译器概念 - 说明编译器的必要性
- 阐述编译器工作流程
回答范例
Vue中有个独特的编译器模块,称为compiler,它的主要作用是将用户编写的template编译为js中可执行的render函数。- 之所以需要这个编译过程是为了便于前端能高效的编写视图模板。相比而言,我们还是更愿意用
HTML来编写视图,直观且高效。手写render函数不仅效率底下,而且失去了编译期的优化能力。 - 在
Vue中编译器会先对template进行解析,这一步称为parse,结束之后会得到一个JS对象,我们称为抽象语法树AST ,然后是对AST进行深加工的转换过程,这一步成为transform,最后将前面得到的AST生成为JS代码,也就是render函数
可能的追问
Vue中编译器何时执行?

在
new Vue()之后。Vue会调用_init函数进行初始化,也就是这里的init过程,它会初始化生命周期、事件、props、methods、data、computed与watch等。其中最重要的是通过Object.defineProperty设置setter与getter函数,用来实现「响应式」以及「依赖收集」
- 初始化之后调用
$mount会挂载组件,如果是运行时编译,即不存在render function但是存在template的情况,需要进行「编译」步骤 compile编译可以分成parse、optimize与generate三个阶段,最终需要得到render function
React有没有编译器?
react 使用babel将JSX语法解析
<div id="app"></div>
<script>
let vm = new Vue({
el: '#app',
template: `<div>
// <span>hello world</span> 是静态节点
<span>hello world</span>
// <p>{{name}}</p> 是动态节点
<p>{{name}}</p>
</div>`,
data() {
return { name: 'test' }
}
});
</script>
源码分析
export function compileToFunctions(template) {
// 我们需要把html字符串变成render函数
// 1.把html代码转成ast语法树 ast用来描述代码本身形成树结构 不仅可以描述html 也能描述css以及js语法
// 很多库都运用到了ast 比如 webpack babel eslint等等
let ast = parse(template);
// 2.优化静态节点:对ast树进行标记,标记静态节点
if (options.optimize !== false) {
optimize(ast, options);
}
// 3.通过ast 重新生成代码
// 我们最后生成的代码需要和render函数一样
// 类似_c('div',{id:"app"},_c('div',undefined,_v("hello"+_s(name)),_c('span',undefined,_v("world"))))
// _c代表创建元素 _v代表创建文本 _s代表文Json.stringify--把对象解析成文本
let code = generate(ast);
// 使用with语法改变作用域为this 之后调用render函数可以使用call改变this 方便code里面的变量取值
let renderFn = new Function(`with(this){return ${code}}`);
return renderFn;
}
Vue complier 实现
- 模板解析这种事,本质是将数据转化为一段
html,最开始出现在后端,经过各种处理吐给前端。随着各种mv*的兴起,模板解析交由前端处理。 - 总的来说,
Vue complier是将template转化成一个render字符串。
可以简单理解成以下步骤:
parse过程,将template利用正则转化成AST抽象语法树。optimize过程,标记静态节点,后diff过程跳过静态节点,提升性能。generate过程,生成render字符串
