一、v-for指令
v-for="(item, index) in/of xxx" :key="yyy"
下面案例中,定义了一个数组persons
, 我们使用v-for
指令进行遍历,遍历的次数即为数组的长度length
。
接受的参数有两个,一个是数组中的每一项p
,另一个参数为数组的索引值index
,并用:key
动态指定每一项的唯一标识key
。
注意:这里的唯一标识key
不会在真实DOM
上,但是会在Vue
生成的虚拟DOM
上。在用DIFF
算法的时候会用到。
具体代码如下所示:
<div id="root">
<ul>
<li v-for="(p,index) in persons" :key="index">
{{p.name}} - {{p.use}}
li>
ul>
div>
<script>
new Vue({
el:'#root',
data:{
persons:[
{id:'001',name:'令狐冲',use:"独孤九剑"},
{id:'002',name:'任盈盈',use:"仙女下凡"},
{id:'003',name:'任我行',use:"吸星大法"}
]
}
})
script>
下面案例中,定义了一个对象person
, 我们使用v-for
指令进行遍历,遍历的次数即为对象的属性的个数。
接受的参数有两个,一个是对象中的每个属性的值value
,另一个参数为对象的属性名key
,并用:key
动态指定每一项的唯一标识key
。
<div id="root">
<ul>
<li v-for="(value,key) of person" :key="key">
{{key}} - {{value}}
li>
ul>
div>
<script>
new Vue({
el:'#root',
data:{
person:{
name:'令狐冲',
use:'独孤九剑',
menpai:'华山派'
}
}
})
script>
下面案例中,定义了一个字符串str
, 我们使用v-for
指令进行遍历,遍历的次数即为字符串的字符个数。
接受的参数有两个,一个是字符串中的每个字符值char
,另一个参数为字符串的索引index
,并用:key
动态指定每一项的唯一标识key
。
<div id="root">
<ul>
<li v-for="(char,index) of str" :key="index">
{{index}} - {{char}}
li>
ul>
div>
<script>
new Vue({
el:'#root',
data:{
str:'笑傲江湖'
}
})
script>
下面案例中,指定遍历次数为5
次,我们使用v-for
指令进行遍历。
接受的参数有两个,一个是数值number
,另一个参数为索引index
,并用:key
动态指定每一项的唯一标识key
。
<div id="root">
<ul>
<li v-for="(number,index) of 5" :key="index">
{{index}} - {{number}}
li>
ul>
div>
<div id="root">
<h2>遍历数组h2>
<ul>
<li v-for="(p,index) in persons" :key="index">
{{p.name}} - {{p.use}}
li>
ul>
<h2>遍历对象h2>
<ul>
<li v-for="(value,key) of person" :key="key">
{{key}} - {{value}}
li>
ul>
<h2>遍历字符串:'笑傲江湖'h2>
<ul>
<li v-for="(char,index) of str" :key="index">
{{index}} - {{char}}
li>
ul>
<h2>遍历指定次数:5次h2>
<ul>
<li v-for="(number,index) of 5" :key="index">
{{index}} - {{number}}
li>
ul>
div>
<script>
new Vue({
el:'#root',
data:{
persons:[
{id:'001',name:'令狐冲',use:"独孤九剑"},
{id:'002',name:'任盈盈',use:"仙女下凡"},
{id:'003',name:'任我行',use:"吸星大法"}
],
person:{
name:'令狐冲',
use:'独孤九剑',
menpai:'华山派'
},
str:'笑傲江湖'
}
})
script>
二、key的作用与原理
key
是虚拟DOM
对象的唯一标识Vue
会根据【新数据
】生成【新的虚拟DOM
】Vue
进行【新虚拟DOM
】与【旧虚拟DOM
】的差异进行比较。旧虚拟DOM
中找到了与新虚拟DOM
相同的key
:
ⅰ. 若【虚拟DOM】中内容没变,直接使用之前的【真实DOM】 !
ⅱ. 若【虚拟DOM】中内容变了,则生成【新的真实DOM】,随后替换掉页面中【之前的真实DOM】.
旧虚拟DOM
中未找到与新虚拟DOM
相同的key
ⅰ. 创建【新的真实DOM】,随后渲染到到页面。
若对数据进行:逆序添加
、逆序删除
等破坏顺序
操作:
ⅰ. 会产生没有必要的【真实DOM】更新==>界面效果没问题,但效率低。
如果结构中还包含输入类的DOM:
i . 会产生【错误DOM】更新==>界面有问题。
<div id="root">
<h2>index作为key引发的问题h2>
<button @click.once="add">在列表最前面:添加一个小六六button>
<ul>
<li v-for="(p,index) in persons" :key="index">
{{p.name}} - {{p.use}}
<input type="text" >
li>
ul>
div>
<script>
new Vue({
el:'#root',
data:{
persons:[
{id:'001',name:'令狐冲',use:"独孤九剑"},
{id:'002',name:'任盈盈',use:"仙女下凡"},
{id:'003',name:'任我行',use:"吸星大法"}
]
},
methods: {
add() {
this.persons.unshift({id:'004',name:'老六',use:'不会武功'})
}
},
})
script>
index
作为key
时,发生错乱原理图,如下所示:id
作为key
时,为什么没有发生错乱原理图,如下所示:key
,比如id
、手机号
、身份证号
、学号
等唯一值
。index
作为key
是没有问题的。三、列表过滤
需求:做一个列表过滤功能,UI如下图所示。在输入框中输入内容实现下面列表的过滤显示。
v-for
指令遍历数组persons
data
中定义属性filPersons
:存放过滤后的内容filter
方法实现过滤<div id="root">
<h2>列表过滤h2>
<input type="text" placeholder="请输入内容" v-model="keyWord">
<ul>
<li v-for="(p,index) in filPersons" :key="index" >
{{p.name}} - {{p.use}} - {{p.sex}}
li>
ul>
div>
<script>
new Vue({
el:'#root',
data:{
keyWord:'',
persons:[
{id:'001',name:'令狐冲',use:"独孤九剑",sex:'男'},
{id:'002',name:'任盈盈',use:"仙女下凡",sex:'女'},
{id:'003',name:'任我行',use:"吸星大法",sex:'男'}
],
filPersons:[]
},
watch:{
keyWord:{
immediate:true,
handler(value){
this.filPersons = this.persons.filter((p)=>{
return p.name.indexOf(value)>=0
})
}
}
}
})
script>
v-for
指令遍历数组persons
filPersons
:存放过滤后的内容filter
方法实现过滤<div id="root">
<h2>列表过滤h2>
<input type="text" placeholder="请输入内容" v-model="keyWord">
<ul>
<li v-for="(p,index) in filPersons" :key="index" >
{{p.name}} - {{p.use}} - {{p.sex}}
li>
ul>
div>
<script>
new Vue({
el:'#root',
data:{
keyWord:'',
persons:[
{id:'001',name:'令狐冲',use:"独孤九剑",sex:'男'},
{id:'002',name:'任盈盈',use:"仙女下凡",sex:'女'},
{id:'003',name:'任我行',use:"吸星大法",sex:'男'}
]
},
computed:{
filPersons(){
return this.persons.filter((p)=>{
return p.name.indexOf(this.keyWord)!==-1
})
}
}
})
script>
四、列表排序
要求:在上述案例中,增加排序功能,分别为升序、降序功能
sortType
属性:2升序、1降序、0原顺序sort
方法:arr.sort(a,b)
,a-b
为升序,b-a
为降序<div id="root">
<h2>列表过滤h2>
<input type="text" placeholder="请输入内容" v-model="keyWord">
<button @click="sortType=2">年龄升序button>
<button @click="sortType=1">年龄降序button>
<button @click="sortType=0">原顺序button>
<ul>
<li v-for="(p,index) in filPersons" :key="p.id" >
{{p.name}} - {{p.use}} - {{p.age}}
li>
ul>
div>
<script>
new Vue({
el:'#root',
data:{
keyWord:'',
sortType:0,
persons:[
{id:'001',name:'令狐冲',use:"独孤九剑",sex:'男',age:20},
{id:'002',name:'任盈盈',use:"仙女下凡",sex:'女',age:19},
{id:'003',name:'任我行',use:"吸星大法",sex:'男',age:50}
]
},
computed:{
filPersons(){
const arr = this.persons.filter((p)=>{
return p.name.indexOf(this.keyWord)!==-1
})
if(this.sortType) {
arr.sort((p1,p2)=>{
return this.sortType === 1 ? (p2.age - p1.age) : (p1.age - p2.age);
})
}
return arr;
}
}
})
script>