在日常开发中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会忽略文本节点)
- **如果前一个元素带有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
下面几个重要的函数都在解析事件/插槽的时候分析过了