认识
一、认识
Vue.js
中的编译源码是组件模版,目标代码是渲染函数。详细而言: Vue.js
模版编译器会首先对模版进行词法分析和语法分析, 得到 AST
模版。接着, 将模版 AST
转换成 JavaScript AST
。 最后根据 JavaScript AST
生成 JavaScript
代码,即渲染函数代码。Vue.js
模版编译器的工作流程如下:
Template 模版 --> 词法分析 --> 语法分析 --> Template 模版 AST --> Transformer --> JavaScript AST --> 代码生成 --> 渲染函数
1.1 模版 AST
AST
是 abstract syntax tree
的首字母 缩写, 即抽象语法树。所谓模版AST
, 其实是用来描述模版的抽象语法树。如下所示:
<div>
<h1 v-if="ok">Vue Template</h1>
</div>
这段模版会被编译成如下 AST
const ast = {
type: 'Root',
children: [
{
type: 'Element',
tag: 'div',
children: [
……
]
}
]
}
可以看到, AST
其实就是一个具有层级结构的对象。**模版AST
**具有与模版同构的嵌套结构。每一颗AST
都有一个逻辑上的根节点,其类型为Root
。模版中真正的根节点则作为Root
节点的children
存在。
通过封装 parse
函数完成对模版的词法分析和语法分析,得到模版AST
。过程如下:
const template = `
<div>
<h1 v-if="ok">Vue Template</h1>
</div>
`
const templateAST = parse(template);
得到 templateAST
之后, 我们对其进行语义分析, 分析如下:
-
检查
v-else
指令是否存在相符的v-if
指令 -
分析属性值是否是静态的, 是否是常量等
-
插槽是否引用上层作用域的变量等
1.2 模版解析
parser
解析器用来将模版字符串解析为模版AST
。解析器的入参是 Template
模版字符串, 解析器通过有限自动状态机会逐个读取字符串模版中的字符, 完成对模版的标记化,并根据一定的规则将整个字符切割为一个个的 Token
。
有限状态机的状态如下:
-
初始状态:
-
标签开始状态: 在初始状态下, 遇到
<
字符, 状态机会迁移到标签开始状态 -
标签名称状态: 在标签开始状态下, 遇到
d
或者p
等字符串, 状态机会进入标签名称状态, 遇到>
字符时, 状态机会从标签名称状态迁移到初始状态, 并记录在标签名称状态下产生的标签名称。 -
文本状 态: 读取到字符串, 状态机进入到文本状态
-
结束标签状态: 读取到
<
, 状态机进入结束标签状态
有以下模版:
<div>
<p> hello </p>
<p> world </p>
</div>
通过 有限状态机 转化为 Tokens
如下:
Tokens
开始标签 <div>