我们先来举个栗子🌰:


如果我们不加key:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
<div id="app">
<div>
<input type="text" v-model="name">
<button @click="add">添加</button>
</div>
<ul>
<li v-for=" item in list">
<input type="checkbox"> {{item.name}}
</li>
</ul>
<script src="./js/vue.js"></script>
<script>
// 创建 Vue 实例,
var vm = new Vue({
el: '#app',
data: {
name: '',
newId: 3,
list: [
{ id: 1, name: '开心超人' },
{ id: 2, name: '花心超人' },
{ id: 3, name: '小心超人' }
]
},
methods: {
add() {
//注意这里是unshift
this.list.unshift({
id: ++this.newId,
name: this.name
})
this.name = ''
}
}
});
</script>

当选中花心超人时,添加大大怪将军后选中的确是开心超人,并不是我们想要的结果,我们想要的是当添加大大怪将军后,应该选中的还是花心超人。


当我们加上key:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
<div id="app">
<div>
<input type="text" v-model="name">
<button @click="add">添加</button>
</div>
<ul>
<li v-for=" item in list" :key="item.id">
<input type="checkbox"> {{item.name}}
</li>
</ul>
<script src="./js/vue.js"></script>
<script>
// 创建 Vue 实例,
var vm = new Vue({
el: '#app',
data: {
name: '',
newId: 3,
list: [
{ id: 1, name: '开心超人' },
{ id: 2, name: '花心超人' },
{ id: 3, name: '小心超人' }
]
},
methods: {
add() {
//注意这里是unshift
this.list.unshift({
id: ++this.newId,
name: this.name
})
this.name = ''
}
}
});
</script>

同样当选中花心超人时,添加大大怪将军后依旧选中的是花心超人。


查过相关文档,图例说明很清晰。

vue和react的虚拟DOM的Diff算法大致相同,其核心是基于两个简单的假设
首先讲一下diff算法的处理方法,对操作前后的dom树同一层的节点进行对比,一层一层对比,如下图:

当某一层有很多相同的节点时,也就是列表节点时,Diff算法的更新过程默认情况下也是遵循以上原则。
比如一下这个情况:

我们希望可以在B和C之间加一个F,Diff算法默认执行起来是这样的:

即把C更新成F,D更新成C,E更新成D,最后再插入E,是不是很没有效率?

所以我们需要使用key来给每个节点做一个唯一标识,Diff算法就可以正确的识别此节点,找到正确的位置区插入新的节点。


总结:

vue中列表循环需加 :key=”唯一标识” 唯一标识可以是item里面id index等,因为vue组件高度复用增加Key可以标识组件的唯一性,为了更好地区别各个组件 key的作用主要是为了高效的更新虚拟DOM 。