在vue.js里面,v-for和v-if是可以一起使用作用在某个元素上,网上看到一篇文章说永远不要把v-for和v-if同时用在同一个元素上,感觉有点瞎扯,官网也注明了可以一起使用的,还把两个指令的优先级给说明了:

当v-if和v-for一起使用时,v-for的优先级更高,为了方便理解举个栗子:

<div id="app">
<ul>
<li v-for="item in Nums" v-if="item%2==0">{{item}}->偶数</li>
<li v-else-if="item%3==0">{{item}}->可以被3整除的奇数</li>
<li v-else>{{item}}->其它奇数</li>
</ul>
</div>
<script>
new Vue({
el:"#app",
data:{
Nums:[0,1,2,3,4,5,6,7,8,9,10,11,12]
}
})
</script>

比较简单昂,就是用v-for循环一个数组,然后分别用v-if、v-else-if和v-else做判断,渲染如下:

很多人刚开始一起用v-for和v-if时多少有点不习惯,如下:

<li v-for="item in Nums" v-if="item%2==0">{{item}}->偶数</li>
<li v-else-if="item%3==0">{{item}}->可以被3整除的奇数</li>
<li v-else>{{item}}->其它奇数</li>

第2和第3行<li>标签的代码里用到了item,但是item是在第一个<li>里定义了,这样不是不能获取到的吗?其实在源码内部,这三行代码都封装为一个返回一个三元表达式的函数了,作为v-for实现代码的一个参数,然后在v-for遍历数组时依次执行这函数来输出数据的

对于例子里的模板经过在编译阶段生成AST对象后会调用generate函数生成render函数,如下:

它会优先处理v-for指令,然后处于v-if、v-else-if、v-else之类的指令(可以看到v-once的优先级高于v-for和v-else),对于例子里的模板生成的render函数如下:

_c(
'div',
{attrs: {"id": "app"}},
[
_c(
'ul',
_l((Nums),function(item) {
return (item % 2 == 0) ? _c('li', [_v(_s(item) + "->偶数")])
: (item % 3 == 0) ? _c('li', [_v(_s(item) + "->可以被3整除的奇数")])
: _c('li', [_v(_s(item) + "->其它奇数")])
})
)
]
)

writer by:大沙漠 QQ:22969969

_l对应的就是v-for的实现函数,可以看到vue内部把v-if的代码封装为了一个匿名函数,传递给了v-for,而在v-for最后实现时,它是通过遍历Nums,依次执行参数2的,_l对应的函数如下:

function renderList(val, render) {              //渲染v-for指令
var ret, i, l, keys, key;
if (Array.isArray(val) || typeof val === 'string') { //如果val是个数组
ret = new Array(val.length); //将ret定义成val一样大小的数组
for (i = 0, l = val.length; i < l; i++) { //遍历val数组
ret[i] = render(val[i], i); //依次调用render函数,参数1为值 参数2为索引 返回VNode,并把结果VNode保存到ret里面   ;例子里的Nums是个数组,因此是执行到这里的
}
} else if (typeof val === 'number') {
ret = new Array(val);
for (i = 0; i < val; i++) {
ret[i] = render(i + 1, i);
}
} else if (isObject(val)) { //如果val是一个对象
keys = Object.keys(val);
ret = new Array(keys.length);
for (i = 0, l = keys.length; i < l; i++) {
key = keys[i];
ret[i] = render(val[key], key, i); //执行的时候传递三个参数,分别是值、key和索引
}
}
if (isDef(ret)) { //如果ret存在(成功调用了)
(ret)._isVList = true; //则给该数组添加一个_isVList属性,值为true
}
return ret //最后返回ret
}

对于对象来说,逻辑是一样的,只是在逻辑上多个几个细分支,就不介绍了。

Vue.js 从源码理解v-for和v-if的优先级的高低的更多相关文章

  1. 从vue.js的源码分析,input和textarea上的v-model指令到底做了什么

    v-model是 vue.js 中用于在表单表单元素上创建双向数据绑定,它的本质只是一个语法糖,在单向数据绑定的基础上,增加了监听用户输入事件并更新数据的功能:对,它本质上只是一个语法糖,但到底是一个 ...

  2. 深入Vue.js从源码开始(二)

    从入口开始 我们之前提到过 Vue.js 构建过程,在 web 应用下,我们来分析 Runtime + Compiler 构建出来的 Vue.js,它的入口是 src/platforms/web/en ...

  3. vue2.x源码理解

    也不知道哪股风潮,钻研源码竟成了深入理解的标配.我只想说一句,说的很对 准备工作 从GitHub上面下载vue的源码(https://github.com/vuejs/vue) 了解下Flow,Flo ...

  4. 一张思维导图辅助你深入了解 Vue | Vue-Router | Vuex 源码架构

    1.前言 本文内容讲解的内容:一张思维导图辅助你深入了解 Vue | Vue-Router | Vuex 源码架构. 项目地址:https://github.com/biaochenxuying/vu ...

  5. [百度地图] 用于类似 DWZ UI 框架的 百度地图 功能封装类 [MultiZMap.js] 实例源码

    MultiZMap 功能说明 MultiZMap.js 本类方法功能大多使用 prototype 原型 实现,它是 ZMap 的多加载版本,主要用于类似 DWZ 这个 多标签的 UI 的框架: 包含的 ...

  6. HashMap源码理解一下?

    HashMap 是一个散列桶(本质是数组+链表),散列桶就是数据结构里面的散列表,每个数组元素是一个Node节点,该节点又链接着多个节点形成一个链表,故一个数组元素 = 一个链表,利用了数组线性查找和 ...

  7. Caffe源码理解2:SyncedMemory CPU和GPU间的数据同步

    目录 写在前面 成员变量的含义及作用 构造与析构 内存同步管理 参考 博客:blog.shinelee.me | 博客园 | CSDN 写在前面 在Caffe源码理解1中介绍了Blob类,其中的数据成 ...

  8. 基于SpringBoot的Environment源码理解实现分散配置

    前提 org.springframework.core.env.Environment是当前应用运行环境的公开接口,主要包括应用程序运行环境的两个关键方面:配置文件(profiles)和属性.Envi ...

  9. jedis的源码理解-基础篇

    [jedis的源码理解-基础篇][http://my.oschina.net/u/944165/blog/127998] (关注实现关键功能的类)   基于jedis 2.2.0-SNAPSHOT   ...

随机推荐

  1. 第二阶段冲刺个人任务——four

    今日任务: 优化统计团队博客结果界面的显示. 昨日成果: 优化统计个人博客结果页面的显示.

  2. docker-Gitlab、GitLab Runner安装

    以下操作均在CentOs下操作 1.Gitlab install ① 启动gitlab docker run --detach \ --hostname 115.30.149.35 \ --publi ...

  3. Bootstrap自带的那些常用插件

    1.Bootstrap自带的那些常用插件. 1.1模态框 模态框的HTML代码放置的位置 务必将模态框的HTML代码放在文档的最高层级内(也就是说,尽量作为 body 标签的直接子元素),以避免其他组 ...

  4. Docker Mysql部署与使用

    参考链接:Docker 安装 Mysql 详解

  5. k8s注册节点提示Docker SystemdCheck]: detected cgroupfs" as the Docker cgroup dr iver. The r ecommended dr fiver is" systemd"

    本篇就不长篇大论了,直接附上解决办法 提示如上,此提示非必要要求,只是建议,但是看着不爽,那就解决它 这是未解决之前的docker信息,现在输入下面的指令 sudo echo -e "{\n ...

  6. C++对于C故有问题的改进

    C++继承了所有的C特性,并且提供了更丰富的语法和特性(OOP支持.模板支持等),并且拥有和C语言同样出色的运行效率.针对C语言的固有问题,C++做出了如下的升级: 所有变量都可以在需要使用时再定义( ...

  7. 隐马尔可夫(HMM)/感知机/条件随机场(CRF)----词性标注

    笔记转载于GitHub项目:https://github.com/NLP-LOVE/Introduction-NLP 7. 词性标注 7.1 词性标注概述 什么是词性 在语言学上,词性(Par-Of- ...

  8. ros之自定义服务数据

    如何自定义服务数据 string name Uint8 age Uint8 sex Uint8 unknown =0 Uint8 male =1 Uint8 female = 2 (上面的是Reque ...

  9. 使用CStatic显示图片(bmp、ico、png)

    一.显示bmp及ico //h文件 CStatic m_static; //cpp文件 CBitmap bitmap; bitmap.LoadBitmapW(IDB_BITMAP); //加载位图 B ...

  10. FFMPEG学习----遍历所支持的封装格式

    #include <stdio.h> extern "C" { #include "libavformat/avformat.h" }; int m ...