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

时间:2017-11-03 13:29:16

标签: javascript vue.js vuejs2

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

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

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

模板:

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

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

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

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

我尝试过的事情:

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

更新

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

<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
    }
},

1 个答案:

答案 0 :(得分:6)

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

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

showDeleteBtn: this.defaultData.showDeleteBtn

当您更新被绑定为showDeleteBtn道具的item的{​​{1}}属性时,会更改子组件中defaultData对象的值。但是,这不会自动更新子组件中的defaultData属性。

最简单的解决方案是使showDeleteBtn成为计算属性而不是showDeleteBtn方法设置的属性:

data

这明确告诉Vue实例在computed: { showDeleteBtn() { return this.defaultData.showDeleteBtn; } } 值更新时更新showDeleteBtn值。

另一个解决方案是让this.defaultData.showDeleteBtn成为道具:

showDeleteBtn

并将props: { defaultData: Object, showDeleteBtn: Boolean }, 的值绑定到父组件的那个prop:

item.showDeleteBtn

这样,对<input-item v-for='(item, index) in items' :key="item.id" :default-data="item" :show-delete-btn="item.showDeleteBtn" @itemAdded="addItemAfter(index)" /> 值的任何更改都将直接反映在子组件的item.showDeleteBtn道具的值中。

这种方式也使得从父范围更清楚一点,如何更改showDeleteBtn上的属性将影响子组件。