第 82 期 - Vue3 中 v - if 指令的模版编译解析
logoFRONTALK AI/1月14日 16:31/阅读原文

摘要

本文以 Vue3 中的 v - if 指令为例,阐述了模版编译过程,包括代码转换、generate 阶段、transform 阶段、baseParse 生成 AST 等内容,展示了如生成三目表达式等关键操作及相关节点属性的处理。

一、代码转换示例

在 Vue3 的 v - if 指令相关的模版编译中,首先给出了一个代码转换的例子。例如有这样的 Vue 模版:

<div id="app">
  <h1 v - if="title">我是 A</h1>
  <p v - else>我是 B</p>
</div>

它最终转换后的代码如下:

export function render(_ctx, _cache, $props, $setup, $data, $options) {
  return (_openBlock(), _createElementBlock("div", _hoisted_1, [
    (_ctx.title)
     ? (_openBlock(), _createElementBlock("h1", _hoisted_2, "我是 A"))
      : (_openBlock(), _createElementBlock("p", _hoisted_3, "我是 B"))
  ]));
}

二、generate 阶段

  1. 生成条件表达式语句
    • 在 generate 阶段,根据 AST 节点类型(如果是 js 条件表达式即 JS_CONDITIONAL_EXPRESSION 类型),会调用genConditionalExpression来生成条件表达式语句。
    • genConditionalExpression函数中,首先从节点获取关键属性如consequentalternate等。如果测试表达式(test)类型是简单表达式(SIMPLE_EXPRESSION),会做相应处理,如判断是否需要括号等操作并调用genExpression生成简单表达式;否则处理节点的其他情况。
    • 在处理条件分支时,会解析consequentalternate属性,分别调用genNode生成相应的表达式。

三、transform 阶段

  1. 基于 AST 的转换内容
    • transform阶段,基于baseParse阶段生成的 AST,并扩展了 AST 节点属性和指令节点的转换。这里的转换内容包含很多语法和指令相关的操作,语法方面如transformOncetransformIf等,指令方面如transformOntransformBind等。
  2. 处理 v - if 相关语法
    • 当判断语法中有if时,会将之前生产的 JS AST 创建branch节点属性,组装新的ifNode来替换原有的节点。
    • 如果是v - else语法,会移除该节点并生成branch节点属性,赋值到兄弟节点的branchs属性上。
    • 在处理v - if语法时,能识别if | else | else - if,会替换v - if的节点并且生成对应的node中的codegenNode属性,在codegenNode属性下追加alternate属性。
    • 调用createCodegenNodeForBranch后生成的节点数据结构包含consequentalternate等属性。

四、baseParse 生成 AST

  1. 生成的 AST 初始状态
    • parse阶段生成的 AST,对比babel AST仅仅扩展了componentsdectives等相关属性,还没有codegenNodebranches等节点属性。并且给出了一个示例的 AST 结构,包含typesourcechildren等众多属性的详细信息。
 
Made by 捣鼓键盘的小麦 / © 2025 Front Talk 版权所有