Vue的v-for为什么要加key

v-for让我们可以基于一个数组来渲染一个列表。官方文档建议尽可能在使用v-for时提供key。为什么呢?

没有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
<div id="app">
<div>
<input type="text" v-model="name">
<button @click="add">添加</button>
</div>
<ul>
<li v-for="(item, i) in list">
<input type="checkbox"> {{item.name}}
</li>
</ul>
<script>
// 创建 Vue 实例,得到 ViewModel
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>
</div>

当我们先选中吕不韦时,添加项羽后选中变成了李斯,这并不是我们想要的结果,我们想要的是当添加项羽后,选中的仍然是吕不韦。

有key的情况

1
2
3
4
5
6
    <ul>
- <li v-for="(item, i) in list">
+ <li v-for="(item, i) in list" :key="item.id">
<input type="checkbox"> {{item.name}}
</li>
</ul>

符合预期,当添加项羽后,选中的仍然是吕不韦

原理分析

Vue虚拟DOM的diff算法会对操作前后的DOM树同一层的节点进行对比,一层一层对比,如下图。当某一层有很多相同的节点时,也就是列表节点时,Diff算法的更新过程默认情况下也是遵循以上原则。

比如,我们希望可以在B和C之间加一个F,Diff算法默认执行起来是这样的:把C更新成F,D更新成C,E更新成D,最后再插入E。

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

参考


----------- 本文结束啦感谢您阅读 -----------

赞赏一杯咖啡

欢迎关注我的其它发布渠道