template 模版编译器,通过解析器、转换器、生成器将其最终转化为 render 渲染函数。
假如存在一段模版如下:
<div>
<p>Vue</p>
</div>
对于模板编译器来讲,它只是一段字符串:
"<div><p>Vue</p></div>"
首先是解析器,对这个字符串进行解析,获得每一个 token,如下所示:
[
{"type": "tag","name": "div"},
{"type": "tag","name": "p"},
{"type": "text","content": "Vue"},
{"type": "tagEnd","name": "p"},
{"type": "tagEnd","name": "div"}
]
接下来解析器根据所得到的 token 来生成抽象语法树,也就是模板的 AST。
转换出来的抽象语法树 AST:
{
"type": "Root",
"children": [
{
"type": "Element",
"tag": "div",
"children": [
{
"type": "Element",
"tag": "p",
"children": [
{
"type": "Text",
"content": "Vue"
}
]
},
]
}
]
}
到此,解析器的工作就顺利完成了。
接下来转换器将上一步得到的模板 AST 转换为 JS AST:
{
"type": "FunctionDecl",
"id": {
"type": "Identifier",
"name": "render"
},
"params": [],
"body": [
{
"type": "ReturnStatement",
"return": {
"type": "CallExpression",
"callee": {"type": "Identifier", "name": "h"},
"arguments": [
{
"type": "StringLiteral",
"value": "div"
},
{
"type": "ArrayExpression",
"elements": [
...
]
}
]
}
}
]
}
最后是生成器,根据上一步所得到的 JS AST,生成具体的 JS 代码:
function render () {
return h('div', [h('p', 'Vue')])
}
由此,我们得出,单文件组件中所书写的 template,对于模板编译器而言只是普通的字符串,然后将其转化为浏览器可以识别的 JS 代码,也就是渲染函数。
Tip:vue 中比较重要的面试题哦!