Vue中v-for删除列表项后DOM显示异常问题求助
问题原因与解决方案
问题根源
v-for使用index作为key导致组件复用错误
Vue通过key值识别列表元素的唯一性,当使用数组index作为key时,删除中间元素后,后续元素的index会自动前移。比如原数组中index=1对应id=24的元素,删除后index=1变成id=25的元素,但Vue会直接复用原index=1的组件实例,不会重新创建,导致该组件仍显示原id=24的旧数据,而原index=2的组件(对应id=25)会被销毁,出现显示异常。组件内部数据未响应prop更新
子组件的specName和specValue仅在mounted钩子中初始化一次,当组件被复用(传入的specprop发生变化)时,mounted不会再次执行,内部数据无法同步更新为新spec的值,进一步加剧显示错误。
解决步骤
1. 替换v-for的key为唯一标识
将父组件中v-for的key从index改为spec.id,利用每个spec的唯一id让Vue准确跟踪元素身份:
<dm-vehicle-spec @_handleRemoveSpec="_handleRemoveSpec" v-for="spec in vehicleSpecs" :key="spec.id" :spec="spec" ></dm-vehicle-spec>
2. 让组件内部数据响应prop变化
提供两种可行方案:
方案一:通过watch监听spec变化更新数据
给子组件添加watch监听spec的变化,及时更新内部数据:
<script> export default { props: ["spec"], data() { return { specName: null, specValue: null, }; }, mounted() { this.updateSpecData(); }, watch: { spec: { immediate: true, // 初始化时立即执行一次 handler(newSpec) { this.updateSpecData(newSpec); }, }, }, methods: { updateSpecData(spec = this.spec) { this.specName = spec.detail_name || null; this.specValue = spec.detail_value || null; }, _handleRemoveSpec() { this.$emit("_handleRemoveSpec", this.spec.id); }, }, computed: { getSpecNameInputName() { return `spec_${this.spec.id}_name`; }, getSpecValueInputName() { return `spec_${this.spec.id}_value`; }, }, }; </script>
方案二:用computed替代内部data(更推荐)
直接通过computed属性绑定prop值,天然具备响应式,无需手动监听:
<script> export default { props: ["spec"], computed: { specName: { get() { return this.spec.detail_name || null; }, set(value) { // 若需同步更新父组件的spec数据,可在此处触发事件 // this.$emit('update-spec', { ...this.spec, detail_name: value }); }, }, specValue: { get() { return this.spec.detail_value || null; }, set(value) { // this.$emit('update-spec', { ...this.spec, detail_value: value }); }, }, getSpecNameInputName() { return `spec_${this.spec.id}_name`; }, getSpecValueInputName() { return `spec_${this.spec.id}_value`; }, }, methods: { _handleRemoveSpec() { this.$emit("_handleRemoveSpec", this.spec.id); }, }, }; </script>
内容的提问来源于stack exchange,提问作者henrikhannewijk
相关产品推荐
相关产品推荐

