数组在修改元素时没有反应,只有在添加或删除时

Array no reactive when modifying an element, only when adding or deleting

我正在处理带有 Vue 组件和 Laravel 的出版物。

我有一个名为 publications.vue 的父组件,它有两个名为 create.vue 和 list.vue 的子组件,并且 list.vue 我有另一个名为 remove.vue 的子组件和 update.vue.

问题是,当我在数组中添加或删除一个发布时,它工作得很好,但是当我修改一个元素时,它没有反应。控制器工作完美,但除非我刷新,否则屏幕上看不到任何东西。

这是我的代码:

<template>
    <div class="main">
        <create
            :user="user"
            v-if="showCreate"
            @create="addPublicationOnClient"
        />
  
        <list 
            v-for="(publication, index) in publications"
            :key="publication.id" :publication="publication" :user="user" 
            @deleted="deletePublicationOnClient(index)" 
            @updated="updatePublicationOnClient(index, ...arguments)"
        />
    </div>
</template>
addPublication(publication) {
    this.publications.unshift(publication); // works perfect
},

deletePublication(index) {
    this.publications.splice(index, 1); // works perfect
},

updatePublication(index, editedPublication) {
     console.log(editedPublication); // shows the correct value of the edited publication
     
     Vue.set(this.publications, index, editedPublication); // do not react. do not show anything
     this.publications.splice(index, 1, editedPublication) // do not react neither. do not show anything
     
     console.log(this.publications); // shows the correct values in the array
}

我真的很感激任何帮助,因为我真的卡住了,我已经阅读了很多帖子,但找不到解决方案。

Vue 在涉及对象数组时有一些非常棘手的行为。

Vue 正在观察你的数组,当数组的 .length 被修改或者它的值之一被修改时,Vue 可以“看到”那个变化。

当您更新数组中对象的字段时,您不会获得反应性,因为对于 Vue 而言,数组并没有改变。这是因为数组的值是对对象的引用,当您更新对象时,这些引用不会改变。

你上面的方法对我来说似乎很好,但同样可能会出现非常奇怪的问题。

我将重点介绍两种解决这些反应性问题的工具。我相信第一个更适合你的情况。

  1. 显式修改数组长度。
updatePublication(index, editedPublication) {
    this.deletePublication(index);
    this.addPublication(index, editedPublication);
}
  1. 使用 :key 强制 re-rendering。当模板中的键更改时,它将强制所有子元素 re-rendering。
<template>
    <div class="main" :key="'updated-'+updated">
    ...
</template>
    data() {
        return {
            updated: 0,
        };
    },

    ...

    updatePublication(index, editedPublication) {
        this.publications.splice(index, 1, editedPublication);
        this.updated++;
    }