Skip to content

Vue 模板编译原理

概述

Vue 的模板编译将 template 转换为 render 函数,分为三个阶段:解析(parse)、转换(transform)、生成(generate)。

一、编译流程

Template String → Parse → AST → Transform → 优化AST → Generate → Render Function

二、解析阶段 (Parse)

AST 节点类型

typescript
interface ElementNode {
  type: 'Element';
  tag: string;
  props: Array<AttributeNode | DirectiveNode>;
  children: TemplateChildNode[];
}

interface InterpolationNode {
  type: 'Interpolation';
  content: ExpressionNode;
}

示例

javascript
const template = '<div><p>{{ msg }}</p></div>';

// AST
{
  type: 'Root',
  children: [{
    type: 'Element',
    tag: 'div',
    children: [{
      type: 'Element',
      tag: 'p',
      children: [{
        type: 'Interpolation',
        content: { content: 'msg' }
      }]
    }]
  }]
}

三、转换阶段 (Transform)

转换目的

  1. 语法糖展开: v-if/v-for/v-model
  2. 静态分析: 标记静态节点
  3. 优化标记: 添加 PatchFlag

静态提升分析

javascript
function isStaticNode(node) {
  return !node.props.some(p => p.type === 'Directive') &&
         node.children.every(isStaticNode);
}

四、生成阶段 (Generate)

javascript
// 模板
<div id="app"><p>{{ msg }}</p></div>

// 生成的 render 函数
function render(_ctx) {
  return (_openBlock(), _createBlock("div", { id: "app" }, [
    _createVNode("p", null, _toDisplayString(_ctx.msg), 1)
  ]))
}

五、指令编译

v-model

javascript
// <input v-model="text" />
_createVNode("input", {
  modelValue: _ctx.text,
  "onUpdate:modelValue": $event => (_ctx.text = $event)
})

v-on

javascript
// <button @click.stop="handleClick">
_createVNode("button", {
  onClick: _withModifiers(_ctx.handleClick, ["stop"])
})

六、编译优化

  • 静态提升: 静态节点只创建一次
  • 事件缓存: 避免重复创建事件函数
  • PatchFlag: 标记动态内容类型

面试高频题

Q1: 模板编译三个阶段?

Parse(解析) → Transform(转换) → Generate(生成)

Q2: 静态提升原理?

将静态 VNode 创建提升到 render 外,多次渲染复用。

Q3: v-if 和 v-for 不能一起用?

Vue 3 中 v-if 优先级更高,但此时 v-for 变量未定义。

前端面试知识库