我们一般在v-for遍历数据的时候会使用到v-bind:key='xxx'那么可以具体的作用是什么,又有什么特殊的作用呢。
作用: key是虚拟DOM对象的标识 也就是说当数据发生变化时 会生成新的虚拟DOM和旧的DOM去对比 而对比要用到就是key标识 通过key来具体比较哪一个数据
规则: (1) 旧虚拟dom中找到了与新虚拟dom相同的key
若虚拟dom中内容没变 直接使用之前的真实dom
若虚拟的dom中内容变了 则生成新的真实dom 随后替代页面中之前的真实dom
(2)旧虚拟dom中未找到与新虚拟dom相同的key
创建新的真实dom 随后渲染到页面
1.我们来看看具体在应用过程中如果不使用key或者key='index'来作为标识符会出现什么问题
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="../vue.js"></script>
</head>
<body>
<div class="root">
<ul>
<li v-for='(p,index) in persons' :key='index'>
{{p.name}}--{{p.age}}
<input type="text">
</li>
</ul>
<button @click.once='add'>添加</button>
</div>
<script>
new Vue({
el:'.root',
data:{
persons: [{
id:'001',name:'某1',age:18
},{
id:'002',name:'某2',age:19
},{
id:'003',name:'某3',age:20
}]
},
methods: {
add(){
const p={id:'004',name:'某4',age:21}
this.persons.unshift(p)
}
},
})
</script>
</div>
</body>
</html>
特殊:这里有特殊的一点就是如果我们把新添加的列表放在最后就不会出现这种问题
2.当我们将key的标识符改为特殊标识符的时候我们可以看一下
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="../vue.js"></script>
</head>
<body>
<div class="root">
<ul>
<li v-for='(p,index) in persons' :key='p.id'>
{{p.name}}--{{p.age}}
<input type="text">
</li>
</ul>
<button @click.once='add'>添加</button>
</div>
<script>
new Vue({
el:'.root',
data:{
persons: [{
id:'001',name:'某1',age:18
},{
id:'002',name:'某2',age:19
},{
id:'003',name:'某3',age:20
}]
},
methods: {
add(){
const p={id:'004',name:'某4',age:21}
this.persons.unshift(p)
}
},
})
</script>
</div>
</body>
</html>
那么为什么会出现这种情况呢?
这里就需要说到虚拟DOM的对比算法了,也就是开头所说到的,在数据生成真实DOM之前Vue会生成虚拟DOM,然后在数据发生变化时,新老的DOM会根据key来对比,如果使用index或者不使用Vue都会将新的列表的第一个index为0开始对比 ,而已经生成的真实DOM数据它不会在改变
总结: key如何选择?
1 最好使用每条数据库唯一标识符作为key 比如 id 手机号 身份证号 学号等
2 如果不存在对比数据的逆序添加 逆序删除等破坏顺序操作 仅用于渲染列表展示
使用index作为key也是没有问题的