【Vue2深度学习】模板编译篇-模板编译总流程

179 阅读3分钟

模板编译总流程

从前面的学习中,我们知道,Vue中的虚拟DOM是由VNode实例化而来。那么VNode的数据源又是从哪里来的?答案是通过模板编译而来。简单来说,就是把用户写的模板进行编译,就会产生VNode。

什么是模板编译

Vue中,把写在标签中的类似于原生HTML的内容称之为模板。

为什么说是类似于原生HTML内容,因为在Vue中,标签中除了原生HTML标签,还会有变量插值,以及v-on、v-if等指令。

这些东西都是在原生HTML语法中不存在的。但是在Vue中,这些东西都被正确识别并显示了,这是为什么呢?

因为模板编译。

Vue会将用户在<template></template>标签中写的内容进行编译,然后把原生HTML的内容找出来,再把非原生HTML也找出来,最后经过一系列的逻辑处理生成渲染函数(render函数),最终经由render函数将模板内容生成对应的VNode。

这一过程称之为模板编译。

模板编译流程

模板编译的主要目标就是生成渲染函数,为了达到此目的,需要三步走。

1.第一步:将模板解析为AST(抽象语法树)

2.第二步:遍历AST标记静态节点

3.第三步:使用AST生成渲染函数

这三步在模板编译中分别抽象出三个模块来实现各自的功能,分别是:

1.解析器

2.优化器

3.代码生成器。

用图表示如下:

image-20220609183124209.png

解析器

解析器的作用就是将模板编译成AST。

在解析器内部,分成了很多小解析器,其中包括过滤器解析器、文本解析器和HTML解析器,然后通过一条主线将这些解析器组装在一起。

过滤器解析器就是用来解析过滤器的。

文本解析器就是用来解析带变量的文本的。例如: hello {{name}}

HTML解析器是用来解析模板的,它是解析器中最核心的模块,每当解析到HTML标签的开始位置、结束位置、文本或者注释时,都会触发钩子函数,然后将相关信息通过参数传递出来。

主线上做的事就是监听HTML解析器,每当触发钩子函数时,就生成一个对应的AST节点。这个AST其实和VNode有点类似,都是使用JS中的对象来表述节点。

优化器

由于静态节点不需要总是重新渲染,所以在生成AST之后,生成渲染函数之前这个阶段,需要遍历一遍AST,给所有的静态节点做一个标记,这样在虚拟DOM中更新节点时,如果发现节点有这个标记,就不会重新渲染它。

优化器的功用就是遍历AST,检测出所有的静态节点并给其打标记。

当AST中的静态节点被打上标记后,每次重新渲染时,就不需要为打上标记的静态节点创建新的虚拟节点,而是直接克隆已存在的虚拟节点。在虚拟DOM更新操作中,如果两个节点是同一个节点且是静态节点,则可以直接跳过更新节点的流程,从而避免做一些无用功,进而提升性能。

代码生成器

代码生成器是模板编译的最后一步,它的作用是将AST转换成渲染函数中的内容(代码字符串)。

例如,一个简单的模板

<div id="NLRX"><p>Hello {{name}}</p></div>

生成的代码字符串是

_c('div',{attrs:{"id":"NLRX"}},[_c('p'),[_v("Hello "+_s(name))]])

当将代码字符串放到渲染函数中并导出到外界后,模板的编译的任务就完成了。