Vue.js研读-模板编译
模板编译
模板编译的主要目标是生成渲染函数。而渲染函数的作用是每次执行它,它就会使用当前最新的状态生成一份新的vnode,然后使用这份vnode进行渲染。
将模板编译成渲染函数
将模板编译成AST(解析器)
遍历AST标记静态节点(优化器)
使用AST生成渲染函数(代码生成器)
解析器
将模板编译成AST
在解析器内部,分成了很多小解析器,其中包括过滤解析器、文本解析器和HTML解析器。然后再通过一条主线将这些解析器组装在一起。
HTML解析器是解析器中最核心的模块,它的作用是解析HTML模板,每当解析到HTML标签的开始位置、结束位置、文本或注释时,都会触发钩子函数,然后将相关信息通过参数传递出来。在解析期间,使用栈来记录层级关系(触发start钩子函数时入栈,触发end钩子函数时出栈)。
事实上,解析HTML模板的过程就是循环的过程,简单来说就是用HTML模板字符串来循环,每轮循环都从HTML模板中截取一小段字符串,然后重复上述过程👆,直到HTML模板被截成一个空字符串时结束。
文本解析器的主要作用是对HTML解析器解析出来的文本进行二次加工,处理带变量的文本。HTML解析器在解析文本时并不会区分文本是否是带有变量的文本,如果是纯文本,不需要进行任何处理;但如果是带变量的文本那个需要使用文本解析器进一步解析。
优化器
优化器的目标是遍历AST,检测出所有静态子树(永远不会变化的DOM节点)并给其打标记
标记静态子树有两点好处:
- 每次重新渲染时,不需要为静态子树创建新节点
- 在虚拟DOM中打补丁的过程中可以跳过
优化器内部实现主要有以下两个步骤:
在AST中找出所有静态节点并打上标记(
static === true
)<p>我是一个静态节点</p>
在AST中供找出所有静态根节点并打上标记(
staticRoot === true
)如果一个节点下边的所有子节点都是静态节点,并且它的父级是动态节点,那么它就是静态根节点
代码生成器
代码生成器是模板编译的最后一步,它的作用是将AST转换成渲染函数中的内容,这个内容称为代码字符串。之后交由渲染函数导出到外界。
代码生成器其实就是字符串拼接的过程。通过递归AST来生成字符串,最先生成根节点,然后在子节点字符串生成后,将其拼接在根节点的参数中,子节点的子节点拼接在子节点的参数中,这样一层一层地拼接,直到最后拼接成完整的字符串。
渲染函数
Vue.js通过将模板编译转换成渲染函数(render function)执行渲染函数就可以得到一个虚拟节点树,使用这个虚拟节点树就可以渲染界面。