html5if判断语句源码,Vue.js 源码分析(十七) 指令篇 v-if、v-else-if和v-else 指令详解...

v-if 指令用于条件性地渲染一块内容。这块内容只会在指令的表达式返回true值的时候被渲染。

v-else-if,顾名思义,充当 v-if 的“else-if 块”,可以连续使用:

也可以使用 v-else 指令来表示 v-if 的“else 块”:

挺好理解的,就和大多数的语言的if()....else if()...else逻辑语句是一样的,例如:

document

vue.config.productiontip=false;

vue.config.devtools=false;

n小于0

no等于0

no大于0

渲染为:

37c51f7110c5ffddd2e38c8767c227fb.png

有两个注意点:

v-else和v-else-if 必须紧跟在带 v-if 或者 v-else-if 的元素之后,一会儿将源码的时候会讲到为什么

因为 v-if 是一个指令,所以必须将它添加到一个元素上。但是如果想切换多个元素呢?此时可以把一个 元素当做不可见的包裹元素,

源码分析

vue内部会把v-if、v-else、v-else-if解析称为一个三元运算符,如果有多个v-else,则三元运算符内再嵌套一个三元运算符,以例子里的为例:

解析模板解析到

n小于0

这个dom元素时会执行到processif()函数

function processif (el) { //第9402行 解析v-if指令

var exp = getandremoveattr(el, 'v-if'); //获取表达式,例如:"no<0"

if (exp) { //如果存在v-if属性

el.if = exp; //增加if属性

addifcondition(el, { //调用addifcondition()函数给el增加一个ifconditions属性,值是一个对象,其中 exp表示当前v-if的值,block是当前ast对象的引用(一会儿给v-else和v-else-if用的)

exp: exp,

block: el

});

} else { //如果不存在v-if属性

if (getandremoveattr(el, 'v-else') != null) { //如果存在else命令,则在el.else上增加一个else属性

el.else = true;

}

var elseif = getandremoveattr(el, 'v-else-if'); //如果存在v-else-if指令,则添加elseif属性

if (elseif) {

el.elseif = elseif;

}

}

}

function addifcondition (el, condition) { //第9453行 增加一个ifconditions属性,

if (!el.ifconditions) {

el.ifconditions = []; //如果ifconditions属性不存在则初始化为一个空数组

}

el.ifconditions.push(condition); //将参数condition这个对象push进来

}

对于v-if节点只是增加一个if和ifconditions属性,对于

n小于0

来说,对应的ast对象增加的属性如下:

c7eca6d2f2c02df869a9ed57ad86c7eb.png

解析模板时,对于v-else和v-else-if来说,并没有把当前对应的ast对象加到ast树中,而是把自己对应的ast对象添加到最近的v-if的ifconditions里,代码如下:

if (currentparent && !element.forbidden) { //第9223行 如果当前对象不是根对象, 且不是style和text/javascript类型script标签

if (element.elseif || element.else) { //如果有elseif或else指令存在(设置了v-else或v-elseif指令)

processifconditions(element, currentparent); //则调用processifconditions()函数

} else if (element.slotscope) { // scoped slot //如果element是作用域插槽

currentparent.plain = false;

var name = element.slottarget || '"default"';(currentparent.scopedslots || (currentparent.scopedslots = {}))[name] = element;

} else {

currentparent.children.push(element);

element.parent = currentparent;

}

}

processifconditions会在之前的ast节点,也就是v-if的ast节点的ifconditions上把当前的ast对象添加进去,如下:

function processifconditions (el, parent) { //第9421行 解析v-else、v-else-if指令

var prev = findprevelement(parent.children); //调用findprevelement获取el之前的ast对象(只查找普通元素ast)

if (prev && prev.if) { //如果prev存在,且它含有v-if指令

addifcondition(prev, { //则调用addifcondition给prev的ifconditions添加一条语句

exp: el.elseif,

block: el

});

} else {

warn$2(

"v-" + (el.elseif ? ('else-if="' + el.elseif + '"') : 'else') + " " +

"used on element without corresponding v-if."

);

}

}

function findprevelement (children) { //第9436行 查找children前一个文本ast对象

var i = children.length;

while (i--) { //遍历children,从后开始

if (children[i].type === 1) { //如果是普通节点

return children[i] //则直接返回该元素

} else {

if ("development" !== 'production' && children[i].text !== ' ') { //开发模式下,如果该节点不是普通节点,则报错

warn$2(

"text \"" + (children[i].text.trim()) + "\" between v-if and v-else(-if) " +

"will be ignored."

);

}

children.pop();

}

}

}

执行完后整个ast对象树如下:

315a1151226791288b31e8e966c0e9fc.png

接下来执行generate生成rendre函数时时发现有有if属性就执行genif()函数:

function genif ( //第10205行 //渲染v-if指令

el,

state,

altgen,

altempty

) {

el.ifprocessed = true; // avoid recursion //避免递归

return genifconditions(el.ifconditions.slice(), state, altgen, altempty) //调用genifconditions函数

}

function genifconditions ( //第10215行 拼凑if表达式 conditions:比如:[{exp: "ok", block: {…}}]

conditions,

state,

altgen,

altempty

) {

if (!conditions.length) { //如果conditions不存在

return altempty || '_e()' //则直接返回altempty

}

var condition = conditions.shift(); //获取内容,比如:{exp: "no<0", block: {…}}

if (condition.exp) { //拼凑三元运算符

return ("(" + (condition.exp) + ")?" + (genternaryexp(condition.block)) + ":" + (genifconditions(conditions, state, altgen, altempty)))

} else {

return ("" + (genternaryexp(condition.block)))

}

// v-if with v-once should generate code like (a)?_m(0):_m(1)

function genternaryexp (el) { //再次调用genelement()函数

return altgen

? altgen(el, state)

: el.once

? genonce(el, state)

: genelement(el, state)

}

}

最后渲染的render函数为:

_c('div',{attrs:{"id":"app"}},[(no<0)?_c('p',[_v("n小于0")]):(no==0)?_c('p',[_v("no等于0")]):_c('p',[_v("no大于0")])])

其中

(no<0)?_c('p',[_v("n小于0")]):(no==0)?_c('p',[_v("no等于0")]):_c('p',[_v("no大于0")])

就是对应的例子里的v-if、v-else、v-else-if结构了

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值