vue3-compiler(一) 认识AST

93 阅读2分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第20天,点击查看活动详情

这次讲compiler模块的parse(将 vue 模板代码编译为渲染函数),认识其中的AST节点。我们来实现一个简单的版本以便理解。

可以用这个链接观察案例:vue-next-template-explorer.netlify.app/

编译的步骤

compiler.png

我们来实现一个简单的,不做兼容和优化(静态提升等)的版本,用几百行代码代替上万的代码

AST

认识

ast.png

类型

const NodeTypes = {
  ROOT: 'ROOT',
  ELEMENT: 'ELEMENT',
  TEXT: 'TEXT',
  SIMPLE_EXPRESSION: 'SIMPLE_EXPRESSION',
  INTERPOLATION: 'INTERPOLATION',
  ATTRIBUTE: 'ATTRIBUTE',
  DIRECTIVE: 'DIRECTIVE',
};

const ElementTypes = {
  ELEMENT: 'ELEMENT',
  COMPONENT: 'COMPONENT',
};
  1. 根节点
{
  type: NodeTypes.ROOT,
  children: [],
}
  1. 纯文本节点
{
  type: NodeTypes.TEXT,
  content: string
}
  1. 表达式节点
// 位于{{ }}之间或者 指令节点的值,总之是 data的变量值
{
  type: NodeTypes.SIMPLE_EXPRESSION,
  content: string,
  // 表达式是否静态。静态可以理解为content就是一段字符串;而动态的content指的是一个变量,或一段js表达式
  isStatic: boolean,
}
  1. 插值节点
{
  type: NodeTypes.INTERPOLATION,
  content: {
    type: NodeTypes.SIMPLE_EXPRESSION, 
    content: string,
    isStatic: false,
  } // 表达式节点
}
  1. 元素节点
{
  type: NodeTypes.ELEMENT,
  tag: string, // 标签名,
  tagType: ElementTypes, // 是组件还是原生元素,
  props: [], // 属性节点数组,
  directives: [], // 指令数组
  isSelfClosing: boolean, // 是否是自闭合标签,
  children: [],
}
  1. 属性节点
{
  type: NodeTypes.ATTRIBUTE,
  name: string,
  value: undefined | {
    type: NodeTypes.TEXT,
    content: string,
  } // 纯文本节点
}
  1. 指令节点
{
  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

待续。