v-for中key的作用与原理

一、虚拟DOM中key的作用key是虚拟DOM对象的标识,当数据发生变化时,Vue会根据新数据生成新的虚拟DOM , 随后Vue会对新虚拟DOM与旧虚拟DOM的差异进行比较 。
二、如何选择key最好使用每条数据的唯一标识作为key,用一个简单的例子说明:
1.用index作为key时点击按钮在列表最前方添加赵六用户
<ul><li v-for="(p,index) of persons" :key="index">{{p.name}}<input type="text"></li><br><button @click="Add">在最前方添加一个用户</button></ul> data () {return {persons: [{id: '01', name: '张三'},{id: '02', name: '李四'},{id: '03', name: '王五'}]}},methods: {Add () {let p = {id: '04', name: '赵六'}this.persons.unshift(p)}}点击以后,页面如下图

v-for中key的作用与原理

文章插图
然而,如果在我点击按钮前 , 在输入框中输入一些内容
v-for中key的作用与原理

文章插图
点击按钮后就会变成
v-for中key的作用与原理

文章插图
很明显,这并不是我们理想中想要呈现的效果 。
2.用id作为key时<ul><li v-for="p of persons" :key="p.id">{{p.name}}<input type="text"></li><br><button @click="Add">在最前方添加一个用户</button></ul>在输入框中输入与之前相同的内容,点击按钮后这次的页面则变成了下图
v-for中key的作用与原理

文章插图
很明显,这次就对了!
三、原因分析为什么用id和index作为key出来的效果天差地别呢,首先来分析一下key的作用原理 。
用index作为key时:
v-for中key的作用与原理

文章插图
首先会根据初始数据生成虚拟DOM,然后将虚拟DOM转为真实DOM,在加入新数据以后,再根据新数据生成新的虚拟DOM,此时Vue并不会再重新将新虚拟DOM直接转为真实DOM,而是进行一个虚拟DOM的对比算法 。如下:
v-for中key的作用与原理

文章插图
首先在新的虚拟DOM中按照顺序取出第一项,然后根据标识“key=0”在旧的虚拟DOM中寻找拥有一样“key=0”的节点,然后开始挨个对比 。
v-for中key的作用与原理

文章插图
第一个节点为文本节点 , Vue发现一个为张三一个为赵六,不一致,于是将新的文本节点赵六转为真实DOM
v-for中key的作用与原理

文章插图
然后来到第二个标签节点input,需要注意的是 , 我们对文本框的输入是在真实DOM中操作的,但在虚拟DOM中两边的标签节点input是一样的,所以这时候Vue不会将它重新转成真实DOM,而是直接复用左边的 。
v-for中key的作用与原理

文章插图
以此类推,key等于1和等于2时,文本节点重新转为真实DOM , 标签节点复用 。
v-for中key的作用与原理

文章插图
当来到key等于3这一项时,发现左边并没有key是等于3的一项,所以这个时候,Vue直接将右边key等于3这一项直接转为真实DOM 。
用id作为key时:
v-for中key的作用与原理

文章插图
首先也是按照顺序取出第一项,然后根据标识“key=04”在左边寻找拥有同样key的一项,发现没有 , 于是直接转为真实DOM 。
v-for中key的作用与原理

文章插图
然后按顺序取出第二项,根据标识“key=01”,在左边寻找也是“key=01”的一项,挨个对比文本节点和标签节点 , 发现两个节点都完全一样,所以直接复用之前的真实DOM 。
v-for中key的作用与原理

文章插图
以此类推 , 李四和王五都是直接复用左边的真实DOM 。
四、总结
  1. 用index作为key可能会引发的问题:若对数据进行逆序添加、逆序删除等破坏顺序的操作时,会产生没有必要的真实DOM更新,此时界面效果没有问题 , 但效率太低 。
  2. 在开发中如何选择key:最好使用每条数据的唯一标识作为key,比如id、身份证号、手机号等 , 如果不存在对数据的逆序添加、逆序删除等破坏顺序操作,仅用于渲染列表用于展示,使用index作为key是没有问题的 。

    推荐阅读