目录
模板编译所介绍的内容是如何让虚拟dom拿到vnode。模板编译再整个渲染过程中的位置,如下图所示:
在底层实现上,vue会将模板编译成虚拟dom渲染函数。当应用内部的状态发生变化时,vue可以结合响应式系统,找出最小数量的组件进行重新渲染以及最小地进行dom操作。
1 概念
模板编译的主要目标是生成渲染函数,而渲染函数的作用是每次执行它,就会使用当前最新的状态生成一份新的vnode,然后使用这个vnode进行渲染。
2 将模板编译成渲染函数
模板编译分为三部分:
1.将模板解析成AST(抽象语法树);
2.遍历AST标记静态节点(由于静态节点不需要总是重新渲染,所以在生成AST之后、生成渲染函数之前这个阶段,需要遍历一遍AST,给所有静态节点做一个标记,在虚拟dom更新时,不会重新渲染静态节点。);
3.使用AST生成渲染函数。
在模板编译中分别抽象出三个模块来实现各自的功能,分别是:
1.解析器;
2.优化器;
3.代码生成器。
模板编译的整体流程如下图所示:
2.1 解析器
解析器的作用:将模板解析成AST;
在解析器内部,分成了很多小解析器,其中包括过滤解析器、文本解析器和html解析器,然后通过主线将这些解析器组装在一起。
过滤器解析器:用来过滤解析器;
文本解析器:用于解析带变量的文本;
html解析器:解析器中最核心的模块,它的作用就是模板解析,每当解析到html标签的开始位置、结束位置、文本或注释时,就会触发钩子函数,然后将相关的参数传递出来。
当html解析器把所有模板都解析完毕后,AST也就生成好了。
2.2 优化器
优化器的目标是遍历AST,检测出所有静态子树(永远不会发生变化的dom节点,标签内没有任何变量或函数的纯文本节点)并给其打标记。
当AST中的静态树被打上标记后,每次重新渲染时,就不需要为打上标记的静态节点创建新的虚拟节点,而是直接克隆已存在的虚拟节点。
总体来说,优化器的作用:避免一些无用功来提升性能。因为静态节点除了首次渲染,后续不需要任何重新渲染操作。
2.3 代码生成器
代码生成器是模板编译的最后一步,它将AST转换成渲染函数中的内容,这个内容称为“代码字符串”。
案例:
<p title="lisa" @click="c">1</p>
编译后:
`with(this){
return _c(
"p",
{
attrs:{ "title":"lisa" },
on: { "click": c }
},
[_v("1")]
)
}`
这样一个字符串最终导出到外界使用时,会将代码字符串放到函数里,这个函数叫作渲染函数。
那么,如何将代码字符串放到函数里?
const code = `with(this){ return "hello lisa" }`
const hello = new Function(code)
hello(); // hello lisa
3 总结
模板编译成渲染函数有三部分内容:先将模板解析成AST,然后遍历AST标记静态节点,最后使用AST生成代码字符串。这三部分内容分别对应三个模块:解析器、优化器、代码生成器。
注:本文章来自于《深入浅出vue.js》(人民邮电出版社)阅读后的笔记整理