Skip to content

Vue 模板

vue 中的模版到最终也是会通过模版编译器编译为渲染函数的形式

所以可以使用h、render 来书写组件,只要返回一个 VNode 就可以描述组件视图

Vue 虚拟 DOM 的结构

模版编译

单文件组件中的模版,对于 模版编译器来讲,就是一堆字符串。它的处理过程是这样的。

模版编译的过程

模版编译的三个阶段

  1. 解析器 (Parser)

    • 输入: 模版字符串
    • 输出: 模版 AST
    • 功能: 将原始模版解析成抽象语法树
  2. 转换器 (Transformer)

    • 输入: 模版 AST
    • 输出: JavaScript AST
    • 功能: 对 AST 进行语义分析和转换
  3. 生成器 (Generator)

    • 输入: JavaScript AST
    • 输出: 渲染函数
    • 功能: 生成最终的可执行代码

可以通过 astexplorer 工具来查看编译后的 AST 结构。

输入模版:

vue
<template>
  <div>
    <h1>hello world</h1>
  </div>
</template>

解析器输出的 模版 AST:

json
{
  "type": 0,
  "children": [
    {
      "type": 1,
      "tag": "template",
      "children": [
        {
          "type": 1,
          "tag": "div",
          "children": [
            {
              "type": 1,
              "tag": "h1",
              "children": [
                {
                  "type": 2,
                  "content": "hello world"
                }
              ]
            }
          ]
        }
      ]
    }
  ]
}

转换器输出的 JS AST:

json
{
  "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": [
              {
                "type": "CallExpression",
                "callee": {
                  "type": "Identifier",
                  "name": "h"
                },
                "arguments": [
                  {
                    "type": "StringLiteral",
                    "value": "hello"
                  }
                ]
              }
            ]
          }
        ]
      }
    }
  ]
}

生成器的结果

js
function render() {
  return h('div', [h('h1', 'hello world')])
}
js
function compile(template) {
  // 1. 解析器
  const ast = parse(template)
  // 2. 转换器
  const jsAst = transForm(ast)
  // 3. 生成器
  const code = generate(jsAst)
}

模版编译的时机

  1. 运行时编译 当通过 CDN 方式引入 Vue 时,模版的编译会在运行时进行,实时将模版转换为渲染函数

  2. 预编译 在工程化的开发环境中,模版会在构建阶段完成编译。编译后是不存在模版的

借助了 vite-plugin-inspect 插件查看文件编译后的结果

最后更新时间: