携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第20天,点击查看活动详情
这次讲compiler
模块的parse
(将 vue
模板代码编译为渲染函数),认识其中的AST
节点。我们来实现一个简单的版本以便理解。
可以用这个链接观察案例:vue-next-template-explorer.netlify.app/
编译的步骤
我们来实现一个简单的,不做兼容和优化(静态提升等)的版本,用几百行代码代替上万的代码
AST
认识
类型
const NodeTypes = {
ROOT: 'ROOT',
ELEMENT: 'ELEMENT',
TEXT: 'TEXT',
SIMPLE_EXPRESSION: 'SIMPLE_EXPRESSION',
INTERPOLATION: 'INTERPOLATION',
ATTRIBUTE: 'ATTRIBUTE',
DIRECTIVE: 'DIRECTIVE',
};
const ElementTypes = {
ELEMENT: 'ELEMENT',
COMPONENT: 'COMPONENT',
};
- 根节点
{
type: NodeTypes.ROOT,
children: [],
}
- 纯文本节点
{
type: NodeTypes.TEXT,
content: string
}
- 表达式节点
// 位于{{ }}之间或者 指令节点的值,总之是 data的变量值
{
type: NodeTypes.SIMPLE_EXPRESSION,
content: string,
// 表达式是否静态。静态可以理解为content就是一段字符串;而动态的content指的是一个变量,或一段js表达式
isStatic: boolean,
}
- 插值节点
{
type: NodeTypes.INTERPOLATION,
content: {
type: NodeTypes.SIMPLE_EXPRESSION,
content: string,
isStatic: false,
} // 表达式节点
}
- 元素节点
{
type: NodeTypes.ELEMENT,
tag: string, // 标签名,
tagType: ElementTypes, // 是组件还是原生元素,
props: [], // 属性节点数组,
directives: [], // 指令数组
isSelfClosing: boolean, // 是否是自闭合标签,
children: [],
}
- 属性节点
{
type: NodeTypes.ATTRIBUTE,
name: string,
value: undefined | {
type: NodeTypes.TEXT,
content: string,
} // 纯文本节点
}
- 指令节点
{
type: NodeTypes.DIRECTIVE,
name: string,
exp: undefined | {
type: NodeTypes.SIMPLE_EXPRESSION,
content: string,
isStatic: false,
}, // 表达式节点
arg: undefined | { //v-if是没参数, undefined
type: NodeTypes.SIMPLE_EXPRESSION,
content: string,
isStatic: true, // 也可以是 v-bind:[class]这样动态的
} // 表达式节点
}
指令节点
<div v-bind:class="myClass" />
<div @click="handleClick" /> //@ = v-on
name: bind, arg: class, exp: myClass 名字,参数,表达式
name: on, arg: click, exp: handleClick
举例子
<div id="foo" v-if="ok">hello {{name}}</div>
{
"type": "ROOT",
"children": [
{
"type": "ELEMENT",
"tag": "div",
"tagType": "ELEMENT",
"props": [
{
"type": "ATTRIBUTE",
"name": "id",
"value": { "type": "TEXT", "content": "foo" }
}
],
"directives": [
{
"type": "DIRECTIVE",
"name": "if",
"exp": {
"type": "SIMPLE_EXPRESSION",
"content": "ok",
"isStatic": false
}
}
],
"isSelfClosing": false,
"children": [
{ "type": "TEXT", "content": "hello " },
{
"type": "INTERPOLATION",
"content": {
"type": "SIMPLE_EXPRESSION",
"isStatic": false,
"content": "name"
}
}
]
}
]
}
parse
待续。