Vuejs——(4)v-if、v-for
版权声明:我萌么~萌!么么哒~http://blog.csdn.net/qq20004604/article/details/52396904
目录(?)[+]
(二十)v-if
①标准v-if用法
简单来说,该值为true则显示该标签,为false则不显示;
如例:
[javascript] view plain copy

- <div id="app">
- <div v-if="abc">{{abc.a}}</div>
- </div>
- <script>
- var vm = new Vue({
- el: "#app",
- data: {
- abc: {
- a: "1"
- }
- }
- })<pre name="code" class="javascript">
</script>
当abc这个对象存在时,显示这一行数据,其内容为abc.a的值;
假如abc这个对象不存在,那么则不显示;
也可以用另外一个变量来控制其是否显示(能否显示决定于该值隐式转换为boolean类型时是true还是false);
例如假如上面有abc这个对象,但这个对象是空对象(没有属性a),但空对象隐式转换后为true,因此会有div,但这个div里没有内容;
②template v-if 包装以同时影响多个html标签;
即假如多个标签(且他们是连续的),被一个变量控制是否显示,那么每个都这么写显然太繁琐,因此用一个template标签将这些标签包裹起来,用v-if标签控制该template标签是否显示,实际渲染时,template标签不会显示,只会显示其内的标签;
如示例:
[javascript] view plain copy
- <div id="app">
- <template v-if="abc">
- <div>{{abc[0]}}</div>
- <div>{{abc[1]}}</div>
- <div>{{abc[2]}}</div>
- </template>
- </div>
- <script>
- var vm = new Vue({
- el: "#app",
- data: {
- abc: [1, 2, 3]
- }
- })
- </script>
由于非空数组是值为true,空数组的值为false,因此方便控制;
另外,这里只是演示,事实上更好的写法的v-for来控制内部三个标签来同时显示(当然,如果不需要显示全部的则不应该这么写);
显示内容:
<divid="app">
<div>1</div>
<div>2</div>
<div>3</div>
</div>
③v-show 用于控制该标签的display样式
他的特点是,dom存在于页面内,已经渲染、事件绑定完毕,区别只是是否显示。
例如:
[javascript] view plain copy
- <div v-show="a">{{test}}</div>
a的值为true,则正常显示;
a的值为false,则自动添加display:none
v-show不支持template写法(即不能同时控制多个同级连续div);
④v-else v-if和v-show的补充语句;
即v-if和v-show的判断为true时,不显示v-else标签的内容;否则显示v-else标签的内容。
例如:
[javascript] view plain copy
- <div id="app">
- <div v-show="a">{{test}}</div>
- <div v-else>def</div>
- </div>
- <script>
- var vm = new Vue({
- el: "#app",
- data: {
- a: true,
- test: "abc"
- }
- })
- </script>
显示abc;
若把data中的a改为false,则显示def;
另外,标签之间需要连续,如以下,v-else则不能正常生效:
[javascript] view plain copy

- <div v-show="a">{{test}}</div>
- <div>another</div>
- <div v-else>def</div>
另外,不要在组件的情况下使用v-else,而是采用v-show=”!变量名”来变相起到v-else的效果
⑤v-if和v-show的比较
|
v-if |
v-show |
渲染时间 |
第一次为真时 |
刚开始就渲染 |
切换形式 |
动态生成,局部编译/卸载 |
控制display属性 |
生成消耗 |
较小(只生成为真的部分) |
较大(生成全部) |
切换消耗 |
较大(切换时需要局部编译) |
较小(因为生成时已经渲染完成) |
v-if是在第一次条件为真时,进行渲染(比如他下面还有其他组件);
v-show因为只是控制display的属性,因此开始就会渲染;
(二十一)v-for列表渲染
①标准写法
[javascript] view plain copy
- <li v-for="i in items">{{i}}</li>
【1】items是一个对象或者数组;
【2】该格式相当于for(var i in items){//略}
【3】插值的i相当于items[i]
【4】该li会被复制多个,然后依次被items[i]渲染,直到渲染完毕;
示例:
[html] view plain copy
- <div id="app">
- <ul>
- <li v-for="i in items">{{i}}</li>
- </ul>
- </div>
- <script>
- var vm = new Vue({
- el: "#app",
- data: {
- items: {
- a: "1",
- b: "2",
- c: "3"
- }
- }
- })
- </script>
结果:
<divid="app">
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
</ul>
</div>
②索引编号:
在标签里使用$index,即表示当前索引在v-for中的编号(从0开始);
例如上面改为:
[javascript] view plain copy
- <li v-for="i in items">{{i}}"s index is {{$index}}</li>
③template v-for 用于包裹多个标签的v-for
简单来说,需要将多个标签都用v-for遍历,那么就需要用template标签。
同样,template在实际渲染的时候不会出现,只是起到一个包裹作用。
如代码:
[javascript] view plain copy
- <div id="app">
- <ul>
- <template v-for="i in items">
- <li>Index is {{$index}}</li>
- <li>Content is {{i}}</li>
- </template>
- </ul>
- </div>
- <script>
- var vm = new Vue({
- el: "#app",
- data: {
- items: {
- a: "1",
- b: "2",
- c: "3"
- }
- }
- })
- </script>
显示结果是:
<ul>
<li>Index is0</li><li>Content is 1</li>
<li>Index is1</li><li>Content is 2</li>
<li>Index is2</li><li>Content is 3</li>
</ul>
④监视数组变动(修改数组)
当data的某个属性是一个数组时,用v-for可以遍历,但显然数组是可能变动的,因此对以下变动也进行数据绑定;
push() 数组末尾添加
pop() 数组末尾取出
shift() 数组开头取出
unshift() 数组开头添加
splice() 删除并插入
sort() 排序
reverse() 数组顺序颠倒
当利用以上方法变更数组时,被渲染的内容会实时更新;
⑤监视数组的改变(用另一个数组进行替换)
但数组从一个数组变为另一个数组时(记得,数组是按引用传递的),数据绑定依然生效;
但前提是使用以下方法:
filter() 过滤,参数是一个函数,取其返回值为true的元素被添加到新数组
concat() 合并两个数组,返回的数组是合并后的
slice() 返回数组的拷贝,从开始索引到结束索引(前含后不含)
⑥track-by(以下推测不完全确定,因为我没数据去测试)
按照说明,假如用一个新的对象数组来替换已有的对象数组(并且两个对象数组其对象的属性不同),那么由于v-for默认是通过数据对象的特征来决定已有作用域和DOM元素的复用程度,可能导致重新渲染整个列表(比如列表很大的话可能会导致效率很低)。
按照我的理解,大概就是从这样一个数组:(我推测是这样的)
[javascript] view plain copy

- items: [
- {name: "a", age: 10},
- {name: "b", age: 11},
- {name: "c", age: 12}
- ]
变成这样
[javascript] view plain copy
- items = [
- {name: "A", height: 150},
- {name: "B", height: 160},
- {name: "C", height: 170}
- ]
会导致列表重新渲染,如果列表内容特别多,那么就可能带来影响效率和性能。
解决这种方法的办法,就是使用track-by,即加入一个包含某特定属性的标识符,当这个属性的标识符其值相等时,则尽可能复用这个已有对象的作用域和DOM元素。
例如标签写法如下:
[html] view plain copy
- <li v-for="item in items" track-by="id">{{item.name}}</li>
数据从:
[html] view plain copy
- items: [
- {id: 1, name: "a", age: 10},
- {id: 2, name: "b", age: 11},
- {id: 3, name: "c", age: 12}
- ]
变为:
[html] view plain copy
- items = [
- {id: 3, name: "A", height: 150},
- {id: 2, name: "B", height: 160},
- {id: 1, name: "C", height: 170}
- ]
那么在替换时,会复用。
注意,复用并不是使用之前同id的对象所在的dom位置,例如并不会将name=C的元素放在原有的name=a的元素的位置(即使他们id都为1),而是依然根据数组下标的顺序来显示数据。
⑦track-by=”$index”(不确定+1)
当数组没有某一个共同属性时(比如上面的id),但依然需要复用的话,那么就用这个。
他会强制v-for进入原位更新模式,片断不会被移动(我推测这个片断指v-for的dom标签),简单的根据对应的索引的值来刷新dom,这种模式可以处理数组中重复的值。(应该是指对于重复的值,比如像上面那种id为同一个数值的,也可以正常复用)。
由于替换方式简单暴力(索引肯定是一样的),所以高效。
————————————————————————
这让数据替换非常高效,但是也会付出一定的代价。因为这时DOM 节点不再映射数组元素顺序的改变,不能同步临时状态(比如 <input>
元素的值)以及组件的私有状态。因此,如果 v-for
块包含 <input>
元素或子组件,要小心使用 track-by="$index"
——————我表示以上这段话没看懂——————
如以下代码,reverse()依然在起作用啊
[javascript] view plain copy
- <div id="app">