parse
processIf
用于处理v-if
:
1 | function processIf(el) { |
我们照常用一个示范html
帮助理解:
1 | <div id="app"> |
上面这段html
会调用processIf
3 次,每次的差别在于attrsMap
里的属性值:
1 | { |
都处理完后,el
上会多出 3 个属性值:
1 | { |
addIfCondition
用于给el.ifConditions
数组塞入新元素:
1 | export function addIfCondition(el: ASTElement, condition: ASTIfCondition) { |
细心的人可能发现了只有if
分支才改变了el.ifConditions
,另外两个分支应该也会有类似的操作,在什么地方做的呢?
在调用完processIf
后,还有一个地方调用了processIfConditions
,它也会操作el.ifConditions
:
1 | if (currentParent && !element.forbidden) { |
很明显我们在处理到v-else-if
和v-else
时,processIfConditions
都会被调用。另外注意这种情况下是不会把当前元素计入currentParent.children
的,只有v-if
节点才被计入了。看看processIfConditions
:
1 | function processIfConditions(el, parent) { |
findPrevElement
用来在前面找到紧挨着v-else-if
和v-else
的那个节点:
1 | // 找到children中第一个element节点 |
最终经过parse
处理,我们的AST
节点上就有了所有分支的相关属性:
1 | { |
注意根节点的children
只有一个元素,这与我们上面讲的一致,只有v-if
才进入了父元素的children
中。Vue template
的一个细节就是有这个处理得出的,后面会说。
generate
处理v-if
的是genIf
函数:
1 | export function genIf(el: any, state: CodegenState, altGen?: Function, altEmpty?: string): string { |
注释很详细,我们直接看最终生成的render
字符串:
1 | ` |
没有涉及新的帮助函数,可以很清楚的看到核心是一个嵌套的三目运算,最终只有条件成立的那个分支才会生成对应的vnode
。
template 小细节
通常情况下,我们的Vue
组件只能有一个根元素,但是使用v-if
可以有多个根元素分支:
1 | <div id="app"> |
正是因为parse
阶段处理v-if
时的特殊代码:
1 | if (!root) { |
currentParent
的children
中只会有v-if
分支的节点,v-else-if
、v-else
节点都会放到el.ifConditions
中,只在条件成立时才渲染出来。