一、列表渲染
1. v-for
文档说明:列表渲染 — Vue.js (vuejs.org)
我们可以用 v-for
指令基于一个数组来渲染一个列表。v-for
指令需要使用 item in items
形式的特殊语法,其中 items
是源数据数组,而 item
则是被迭代的数组元素的别名。
例:
<ul>
<!-- 循环数组 -->
<p>循环数组: {{arr}}</p>
<li v-for="(item,index) in arr">
<p>item: {{item}}-----index: {{index}}</p>
</li>
<hr>
<!-- 循环对象 -->
<p>循环对象: {{obj}}</p>
<li v-for="(item, name, index) in obj">
<p>name: {{name}}-----item: {{item}}-----index: {{index}}</p>
</li>
<hr>
<!-- 遍历字符串 -->
<p>遍历字符串: {{word}}</p>
<li v-for="(item, index) in word">
<p>item: {{item}}-----index: {{index}}</p>
</li>
<hr>
<!-- 遍历指定次数 -->
<p>遍历指定次数: 5</p>
<li v-for="(item, index) in 5">
<p>item: {{item}}-----index: {{index}}</p>
</li>
</ul>
data() {
return {
arr: [1, 2, 3, 4, 5],
obj: {
name: "Evan You",
age: "36",
sex: "男"
},
word:"HUAWEI终见曙光",
}
},
当处于同一节点,v-for
的优先级比 v-if
更高,这意味着 v-if
将分别重复运行于每个 v-for
循环中。当只想为部分项渲染节点时,这种优先级的机制会十分有用。但是不推荐在同一元素上使用 v-if
和 v-for
例:
<!-- v-for和v-if一起使用 -->
<hr>
<ul>
<li v-for="(item, index) in str" v-if="item.age > 40">
<p>姓名:{{item.name}}-----年龄:{{item.age}}</p>
</li>
</ul>
<!-- 用template解决不写在同一元素上 -->
<hr>
<ul>
<template v-for="(item, index) in str">
<li v-if="item.age < 40">
<p>姓名:{{item.name}}-----年龄:{{item.age}}-----职业:{{item.prof}}</p>
</li>
</template>
</ul>
data() {
return {
str: [
{ id: 1, name: "尤雨溪", prof: "Web", age: 36 },
{ id: 2, name: "詹姆斯", prof: "sport", age: 38 },
{ id: 3, name: "杜兰特", prof: "sport", age: 33 },
{ id: 4, name: "乔丹", prof: "sport", age: 60 },
{ id: 5, name: "库里", prof: "sport", age: 32 },
{ id: 6, name: "科比", prof: "sport", age: 44 },
]
}
},
2. 数组更新检测
文档说明:列表渲染 — Vue.js (vuejs.org)
Vue2中:
-
新增值
arr[0] = 赋值 新增不会被vue检测到,数据会增加,页面不会变化;
obj.属性名 =赋值 新增不会被vue检测到,数据会增加,页面不会发生变化;
-
对象添加,使页面同步修改。
vm. s e t ( O b j e c t , k e y , i t e m ) 或 t h i s . set(Object, key, item) 或 this. set(Object,key,item)或this.set(Object, key, item) 或 Vue.set(vm.Object, key, item)
-
修改数组
重新赋值整个数组 filter,map ;
利用js,修改原数组,触发监听,相关API有:
-
push()
-
pop()
-
shift()
-
unshift()
-
splice()
-
sort()
-
reverse()
例:
<button @click="addArr">点击添加</button>
<button @cilck="delArr">点击删除</button>
<p v-for="item in arr">{{item}}</p>
<!-- 过滤 -->
<button @click="strChange">点击</button>
<p v-for="item in str">{{item.name}}--{{item.age}}</p>
<!-- 对象添加属性 -->
<button @click="objAddChange">点击</button>
<p v-for="(item,index) in obj">{{index}}--{{item}}</p>
data() {
return {
arr: [1, 2, 3, 4, 5],
str: [
{ id: 1, name: "尤雨溪", prof: "Web", age: 36 },
{ id: 2, name: "詹姆斯", prof: "sport", age: 38 },
{ id: 3, name: "杜兰特", prof: "sport", age: 33 },
{ id: 4, name: "乔丹", prof: "sport", age: 60 },
{ id: 5, name: "库里", prof: "sport", age: 32 },
{ id: 6, name: "科比", prof: "sport", age: 44 },
]
}
},
methods: {
addArr(){
// 数组添加
this.arr.push(666);
},
delArr(){
// 删除末尾
this.arr.pop();
},
// 过滤
strChange(){
this.str = this.str.filter(item=>{
return item.age < 40;
})
},
// 对象添加
objAddChange(){
this.$set(vm.obj, "prof", "Web");
}
}
3. key绑定
key
的特殊 attribute 主要用在 Vue 的虚拟 DOM 算法,在新旧 nodes 对比时辨识 VNodes。如果不使用 key,Vue 会使用一种最大限度减少动态元素并且尽可能的尝试就地修改/复用相同类型元素的算法。而使用 key 时,它会基于 key 的变化重新排列元素顺序,并且会移除 key 不存在的元素。
**例:**往前添加时输入框中的内容与之前对应的姓名发生了顺序的的错误。
<button @click="addObjChange">点击</button>
<ul>
<li v-for="(item,index) in str">
<span>{{item.name}}--{{item.age}}--{{item.id}}</span>
<input type="text">
</li>
</ul>
data() {
return {
str: [
{ id: 1, name: "尤雨溪", prof: "Web", age: 36 },
{ id: 2, name: "詹姆斯", prof: "sport", age: 38 },
{ id: 3, name: "杜兰特", prof: "sport", age: 33 },
{ id: 4, name: "乔丹", prof: "sport", age: 60 },
{ id: 5, name: "库里", prof: "sport", age: 32 },
]
}
},
methods: {
addObjChange() {
// 往后添加
this.str.push({ id: 6, name: "科比", age: 44 });
// 往前添加
// this.str.unshift({ id: 6, name: "科比", age: 44 });
}
}
往后添加:
往前添加:
解决:
<li v-for="(item,index) in str" :key="item.id">...</li>
key原理图:
总结:
key主要用在 Vue 的虚拟 DOM 算法,vue使用key时会基于 key 的变化来渲染唯一标识符,不写key 则默认为index。
新的节点和旧的节点不一样 => 重新创建渲染
虚拟DOM中的key作用:key是虚拟dom对象的标识,当数据发生变化时,Vue会根据新数据生成的虚拟dom,随后和旧虚拟dom中的key值进行对比。
对比规则:
旧虚拟dom中找到了与新的虚拟DOM相同的key;
若虚拟dom中的内容未变,直接使用之前的真实dom;
若虚拟dom中内容变了,则生成新的真实dom,随后替换掉页面中之前的真实dom节点。
旧虚拟dom中未找到与新的虚拟DOM相同的key,创建新的真实dom,之后渲染到页面。
用index作为key可能引发的问题:
对数据的逆序添加,逆序删除,破坏顺序,会产生没有必要的真实DOM更新。
工作怎么使用key?
最好是使用每一条数据的唯一标识作为key,比如 手机号,学号等;
不存在对数据的逆序添加,删除,破坏顺序等操作,仅用于展示,可以直接使用index。
二、其他指令
1. v-once
只渲染元素和组件一次。随后的重新渲染,元素/组件及其所有的子节点将被视为静态内容并跳过。这可以用于优化更新性能。
<p v-once>{{arr}}</p>
<button @click.once="fun">点击</button>
fun() {
console.log(vm.arr);
this.arr++;
}
2. v-cloak
这个指令保持在元素上直到关联实例结束编译。和 CSS 规则如 [v-cloak] { display: none }
一起用时,这个指令可以隐藏未编译的 Mustache 标签直到实例准备完毕。
[v-cloak] {
display: none;
}
<div v-cloak>
{{ arr }}
</div>
不会显示,直到编译结束。
3. v-pre
跳过这个元素和它的子元素的编译过程。可以用来显示原始 Mustache 标签。跳过大量没有指令的节点,会加快编译。
<span v-pre>{{ this will not be compiled }}</span>