Vue源码解析:模板编译v-if与codegen(五)

2,976 阅读2分钟

在日常开发中v-if/v-for指令的使用频率很高。本文将通过分析Vue如何处理这两种指令,来梳理前四篇模板编译文章,及最后的codegen过程。

parseHTML

在利用正则逐个解析template字符串的时候,会处理v-if指令两次

第一次:start(processIf)

v-if逻辑

1. 为元素添加if属性,其值为v-if对应的表达式

2. 调用addIfCondition为元素添加ifCondition属性,其值为数组,将表达式推入数组中。数组的元素为具有exp属性与block属性对象。其值分别为表达式与当前解析的元素。

v-else-if逻辑

1. 为元素添加elseif属性,其值为v-else-if对应的表达式

v-else逻辑

1. el.else = true

第二次:end(closeElement)

在closeElement的时候会调用processIfConditions。

另外,带有v-else-if/v-else指令的元素是不会被推入父元素的children数组中。

processIfConditions逻辑

1. 找到当前元素的前一个相邻非文本节点的元素(Vue会忽略文本节点)

  1. **如果前一个元素带有if指令:**提取v-else-if指令表达式并和元素一起构建成一个对象,推入带有v-if元素的ifCondition数组中

注意:

1. v-if/v-else-if/v-else,所在元素都是平级的

2. v-else-if/v-else 元素是不会与父元素建立父子关系的

3. 带有v-if指令的元素具有ifCondition属性,气质为一个数组,数组依次存放 v-if/v-else-if指令对应的元素。

optimize

makeStatic/makeStaticRoot都会对ifConditions做处理,核心就是处理数组元素的block元素。

codegen

generate函数是生成字符串的,其参数为解析生成的ast节点。

调用genElement生成code字符串。

最后返回的是with函数,with函数的参数this,其实是vm实例。with函数内部的作用域就是vm实例。

genElement

函数逻辑很长,这里只分析genIf

genIf

为el添加标记,优化

genIfConditions

核心就是递归调用此函数,每次都从元素的ifCondition数组中从头依次取出元素,然后生成字符串。

这里要注意的是在 if(condition.exp) 逻辑分支中是返回的字符串

最后

codegen返回的带有_c()/_t()等字符串的字符串。
这些都会在组件渲染的时候调用。

其值如下:\src\core\instance\render-helpers

下面几个重要的函数都在解析事件/插槽的时候分析过了

参考:ustbhuangyi.github.io/vue-analysi…