Vue.js不会使用v-for重新渲染组件

Ale*_*der 1 javascript vue.js vuejs2

我正在尝试制作一个多文本输入组件.有一个父Vue组件来管理单个字段和一个组件用于单个输入.

父组件通过v-for渲染子组件,该组件绑定到对象数组.

data() {
    return {
        lastItemId: 0,
        items: [{ id: this.lastItemId, value: '', showDeleteBtn: false}]
    }
},
Run Code Online (Sandbox Code Playgroud)

模板:

<div>
    <input-item v-for='(item, index) in items'
                :key="item.id"
                :default-data="item"
                @itemAdded="addItemAfter(index)"></input-item>
</div>
Run Code Online (Sandbox Code Playgroud)

每当用户开始输入列表中的最后一个字段时,我发出一个事件,在其后面添加一个新的文本字段.

addItemAfter(index) {
    if (index == this.items.length - 1) {
        this.items.push({
            id: ++this.lastItemId,
            value: '',
            showDeleteBtn: false
        });
    }
}
Run Code Online (Sandbox Code Playgroud)

这很好用.但是,我还需要更新当前索引处的项目以显示该字段附近的删除按钮.无论我做什么,Vue都不会重新渲染该组件,除非我为该索引设置了一个具有不同ID的对象 - 这不是我想要的.

我尝试过的事情:

this.items[index].showDeleteBtn = true;
Run Code Online (Sandbox Code Playgroud)
let item = this.items[index];
item.showDeleteBtn = true;
this.$set(this.items, index, item);
Run Code Online (Sandbox Code Playgroud)
let item = this.items[index];
item.showDeleteBtn = true;
this.items.splice(index, 1, item);
Run Code Online (Sandbox Code Playgroud)
this.$set(this.items[index], 'showDeleteBtn', true);
Run Code Online (Sandbox Code Playgroud)

更新

这是子组件的这个问题部分中最重要的部分:

<button class="btn text-danger" v-show="showDeleteBtn" @click.prevent="removeItem">
    <i class="glyphicon glyphicon-remove"></i>
</button>

// ....................................

props: ['defaultData'],

data() {
    return {
        itemId: this.defaultData.id,
        item: this.defaultData.value,
        showDeleteBtn: this.defaultData.showDeleteBtn
    }
},
Run Code Online (Sandbox Code Playgroud)

tha*_*ksd 6

更新项目时未显示删除按钮的原因是showDeleteBtn子组件的属性值未更新.

该值未更新,因为data方法中设置的Vue实例属性仅在初始化时设置一次.所以,showDeleteBtn只在data方法中设置一次:

showDeleteBtn: this.defaultData.showDeleteBtn
Run Code Online (Sandbox Code Playgroud)

当您更新被绑定的showDeleteBtn属性item作为defaultDataprop时,它会更改defaultData子组件中对象的值.但是,这不会自动更新showDeleteBtn子组件中的属性.


最简单的解决方案是创建showDeleteBtn一个计算属性而不是该data方法设置的属性:

computed: {
  showDeleteBtn() {
    return this.defaultData.showDeleteBtn;
  }
}
Run Code Online (Sandbox Code Playgroud)

这明确告诉Vue实例更新showDeleteBtn值,this.defaultData.showDeleteBtn如果它发生了变化.


另一种解决方案是制作showDeleteBtn道具:

props: { defaultData: Object, showDeleteBtn: Boolean },
Run Code Online (Sandbox Code Playgroud)

item.showDeleteBtn从父组件绑定到该prop 的值:

<input-item 
  v-for='(item, index) in items'
  :key="item.id"
  :default-data="item"
  :show-delete-btn="item.showDeleteBtn"
  @itemAdded="addItemAfter(index)"
/>
Run Code Online (Sandbox Code Playgroud)

这样,对值的任何更改item.showDeleteBtn都将直接反映在showDeleteBtn子组件的prop 的值中.

这种方式还使得从父作用域更清楚地了解如何更改该属性item将影响子组件.