Vue.js删除数组指定对象时始终误删最后一项且索引传参为undefined的问题
问题成因
- 子组件未获取到正确的index值:父组件在
v-for循环中虽然生成了遍历下标index,但未将其作为prop传递给favorites-edit-component子组件;子组件点击事件中写的removeItem(this.index),因组件实例上不存在index属性,传入的参数固定为undefined。 - 父组件删除逻辑错误:父组件的
removeItem方法中使用splice(this.favorites_list.indexOf(index), 1)定位待删除项,由于传入的index是数值类型的循环下标,并非数组中存储的元素对象,indexOf无法匹配到对应位置,最终返回-1;而JS中splice(-1, 1)的固定行为是删除数组最后一位元素,这就是无论点击哪个删除按钮,最终都移除数组末尾项的核心原因。
修复步骤
1. 父组件向子组件传递index参数
修改父模板中子组件的调用代码,将循环生成的index通过prop传入组件:
<favorites-edit-component v-for="(favorite, index) in favorites_list" :key="favorite.id" :favorite="favorite" :index="index" />
2. 子组件修正props定义与点击事件逻辑
在子组件的props中新增对index的接收,同时将点击事件中错误的this.index替换为从prop获取的index值:
Vue.component('favorites-edit-component', { template: ` <div class="column is-half"> <button class="button is-fullwidth is-danger is-outlined mb-0"> <span>{{ favorite.name }}</span> <span class="icon is-small favorite-delete" @click="removeItem(index)"> <i class="fas fa-times"></i> </span> </button> </div> `, props: { favorite: Object, index: Number // 新增接收index prop }, methods: { removeItem: function(index) { this.$parent.removeItem(index); }, } });
注意:Vue模板绑定事件时不需要额外添加
this.前缀,直接使用渲染作用域内的变量即可。
3. 修正父组件的删除方法
直接使用传入的index作为splice的删除起始位置,移除错误的indexOf调用:
new Vue({ el: '#favorites-modal-edit', data: function() { return { favorites_list }; }, methods: { addItem: function() { console.log('Added item'); }, removeItem: function(index) { // 直接根据传入的下标删除对应位置元素 this.favorites_list.splice(index, 1); }, }, });
可选优化方案
- 组件通信不要依赖
$parent直接调用父组件方法,可替换为自定义事件触发:子组件内通过this.$emit('remove-item', index)向父组件抛事件,父组件在子组件标签上通过@remove-item="removeItem"监听事件并执行删除逻辑,降低组件间耦合度。 - 因已使用
favorite.id作为循环唯一key,删除操作也可直接传递待删除项的id,在父组件中通过id匹配元素位置后删除,避免动态列表下标错位的问题。
内容的提问来源于stack exchange,提问作者user12394904
相关产品推荐
相关产品推荐

