Vue.js使用index作为v-for的key时列表删除异常问题求解
问题原因
这个问题的核心是v-for使用数组下标index作为key导致的虚拟DOM节点复用异常:
- Vue的虚拟DOM Diff算法依赖
key判断列表节点是否可复用,key是节点的唯一身份标识 - 当你用
index作为key时,key会跟随数组元素的位置变化自动更新。比如数组原有4个元素下标为0/1/2/3,删除下标为2的倒数第二项后,原有下标为3的元素下标会变为2 - 此时Vue检测到列表最终只有3个元素,对应
key为0/1/2,会判定最后一个key=3的节点需要移除,而key=2的节点只是内容更新,最终渲染出来就会表现为“最后一项被删除”,实际上数组本身的数据是正确的,只是渲染层出现了复用错误。
修复方案
给每个数组项添加唯一不变的标识作为key,不要使用动态变化的下标:
- 修改JavaScript逻辑,给每个item新增唯一id字段:
Vue.createApp({ data() { return { parentMessage: 'Parent', nextId: 3, // 初始id从3开始,对应原有2条数据的id items: [ { id: 1, message: 'Foo' }, { id: 2, message: 'Bar' } ] } }, methods: { removeItem(index){ this.items.splice(index, 1); }, addItem(){ this.items.push({ id: this.nextId++, // 每次新增id自增,保证唯一 message: "hello" }); } } }).mount('#array-with-index')
- 修改HTML中
v-for的key绑定:
<ul id="array-with-index" class="demo"> <li v-for="(item, index) of items" :key = "item.id"> {{ parentMessage }} - {{ index }} - {{ item.message }} <button @click = "removeItem(index)"> remove </button> </li> <button @click = "addItem"> add </button> </ul>
修改后每个节点的key跟随元素本身,不会因为数组顺序、长度变化而改变,Diff算法可以准确识别需要删除的节点,不会出现复用错误。
注意:仅当列表完全静态、不会发生增删、排序操作时,才可以使用
index作为key,其余场景都建议使用业务唯一标识作为key。
内容的提问来源于stack exchange,提问作者Haizec
相关产品推荐
相关产品推荐

