Vue脚手架最新版eslint对vfor key值的检验比较严格,不给就报错?!Vue v-for key值到底要不要给? 给的话一定要给唯一标识吗?这里先给结论:
- 数组元素下标不会变化,key值给index即可
- 数组元素可能变化,key值给唯一标识
Vue渲染列表与"就地更新"策略
请看以下的例子:
DOM中渲染数组,同时有一个按钮用于反转数组。
<div id="app">
<!-- 数组反转按钮 -->
<button @click="reverseArr">反转</button>
<!-- 渲染数组的列表 -->
<ul>
<li v-for="(item, index) in songList">
{{item.name}}
</li>
</ul>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
songList: [
{
name: '无人之岛',
id: 1
},
{
name: '晴天',
id: 2
}
]
},
methods: {
// 反转数组
reverseArr () {
this.songList.reverse()
}
}
})
</script>
问题:data属性数组反转到DOM渲染元素的反转,你猜Vue是如何渲染的? 两种方案:
//方案1: 不修改dom,交换dom的值
lidom0.textContent=songList[1]
lidom1.textContent=songList[0]
//方案2: 交换dom位置
parentDom = lidom0.parentNode
parentDom.insertBefore(lidom1,lidom0);
以上两种方案都可以达到渲染元素的反转,但是性能相比如何呢?操作DOM是比较耗性能的,所以方案1更优。而Vue默认用的就是第一种方案,叫做"就地更新",官方文档链接cn.vuejs.org/v2/guide/li…
为了验证这个结论,以下在渲染元素旁边放一个input框,并输入不同值,当点击按钮反转数组时,元素值交换了位置,但是input框的值并没有变
<li v-for="(item, index) in songList">
<input/>
{{item}}
</li>
key值设置为唯一标识总是高效吗?
- 当点击按钮反转数组时,元素值交换了位置,但是input框的值也交换了。
- 说明渲染列表使用了以上的方案2,也就是dom位置交换了。这是低效的渲染方式,所以有时候key值设置为唯一标识反而低效!
- 这如何解释呢?其实给key值,Vue内部就可以区分不同li节点,以便在需要时,交换li
<li v-for="(item, index) in songList" :key="item.id">
<input/>
{{item}}
</li>
key值设置为index
当点击按钮反转数组时,元素值交换了位置,但是input框的值并没有变。情况和不给key效果一样。
因为当data属性数组反转后,index也变了,并不能唯一标识li,Vue内部无法根据key值来区别li节点
<li v-for="(item, index) in songList" :key="index">
<input/>
{{item}}
</li>
总结
其实如果key值给唯一标识总是高效的话,Vue v-for在内部实现时顺手给它所在的dom上添加一个唯一标识,比如时间戳,行不行?完全没问题。实际项目中,90%以上情况,就拿到后端返回数组,作为data属性,然后结构中v-for渲染,或者在数组末追加或删除项,所以Vue渲染时只需要在末尾追加或者删除dom,无须区分渲染节点。这个时候不给key或者key给index效果都一样。关键时这种情况占90%吧。另外如果需要在数组中间插入项时,这个时候key值给唯一标识,才会涉及虚拟DOM diff,关于这个资料一大堆,就不展开了。 知乎答主经常说一句:抛开剂量谈危害。在这里也是适用的,不能因为10%的情况下key值设置为唯一标识性能是提高的,就认为所有时候都该设置唯一标识吧。欢迎讨论。