【问题标题】:Vue.js doesn't re-render components with v-forVue.js 不会使用 v-for 重新渲染组件
【发布时间】:2018-04-16 06:06:52
【问题描述】:

我正在尝试制作一个多文本输入组件。有一个父 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
    }
},

【问题讨论】:

  • 好吧,v-for 不必重新渲染 - 数组没有改变。 input-item 组件必须重新渲染,并且看起来不需要。那么你能分享他们的代码/标记吗?
  • 我更新了问题。
  • data 方法中设置的属性在初始化时设置一次。它们不会更新以响应 defaultData 属性的更改。
  • 用computed()代替怎么样?
  • 澄清一下:defaultData prop 的值将随着绑定到 prop 的 item 值的变化而更新。但是data 方法不会再次被调用来更新showDeleteBtn 数据属性。您可以使用计算的,或者只指定一个 showDeleteBtn 属性并通过 :show-delete-btn="item.showDeleteBtn"

标签: javascript vue.js vuejs2


【解决方案1】:

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

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

showDeleteBtn: this.defaultData.showDeleteBtn

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


最简单的解决方案是将showDeleteBtn 设为计算属性,而不是通过data 方法设置的属性:

computed: {
  showDeleteBtn() {
    return this.defaultData.showDeleteBtn;
  }
}

这显式地告诉 Vue 实例在 showDeleteBtn 值发生变化时将其更新为 this.defaultData.showDeleteBtn 的值。


另一种解决方案是让showDeleteBtn 成为道具:

props: { defaultData: Object, showDeleteBtn: Boolean },

并将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)"
/>

这样,item.showDeleteBtn 的值的任何变化都会直接反映在子组件的 showDeleteBtn 属性的值上。

这种方式还可以让父范围更清楚地了解更改 item 上的该属性将如何影响子组件。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-02-08
    • 2019-04-14
    • 1970-01-01
    • 1970-01-01
    • 2018-10-23
    • 2021-06-05
    • 2020-12-01
    • 2020-02-13
    相关资源
    最近更新 更多