Vue 反应性问题,需要一些解释

Vue reactivity issue, need some explanations

我已经删除了我代码中大部分无用的部分,所以如果这段代码真的没有意义,请不要担心,它只是向您展示哪些部分不起作用。

首先,我从名为 objects:

的基本数组创建一个数组
objects: [
        {
          text: "I dont trigger stuff",
        },
        {
          "text": "I dont trigger stuff",
        },
        {
          text:"I trigger stuff",
          activated: undefined,
        },
],

创建函数

created() {
    const newArray = [];

    this.objects.forEach(anObj => {
      anObj.activated = false;
      newArray.push(anObj);
    });

    this.filteredObjects = newArray;
},

我将属性 activated 初始化为false。在我的真实代码中,我没有使用 forEach,而是 find,但结果是一样的。

然后,我显示几个按钮来触发 "activation"

<button
    v-for="(myObj, index) in filteredObjects"
    :key="index"
    @click="activateObject(myObj, index)">
    {{ myObj.text }}
</button>

被触发的函数是这个:

activateObject(anObj, anObjIndex) {
      this.$set(this.filteredObjects[anObjIndex], 'activated', !anObj.activated)
},

我的目标是更新 activated 属性.

为了检查反应性是否有效,我有一个观察者:

watch: {
    filteredObjects: {
      handler() {
          alert('called')
      },
      deep: true,
    }
},

我有两个问题:

1/ 由于所有对象的所有 activated 属性都设置为 false,为什么只有一个工作,属性 最初设置为 undefined?

2/ 如果我将激活函数更新为:

activateObject(anObj, anObjIndex) {
      anObj.activated = !anObj.activated;
      this.$set(this.filteredObjects, anObjIndex, anObj);
},

效果很好。谁能解释一下为什么,有什么区别?

在这两种情况下,VueJS Devtools 在单击刷新时都会显示更新后的值。这是一个反应性问题。

您可以在此处找到 fiddle:

https://jsfiddle.net/dv1jgneb/

来自Docs

Since Vue performs the getter/setter conversion process during instance initialization, a property must be present in the data object in order for Vue to convert it and make it reactive.

这解释了为什么只有第三个按钮 "trigger stuff"。

因此,您可以在 data() 中添加该属性,或者如文档中所述,使用 this.$set:

this.objects.forEach(anObj => {
  this.$set(anObj, 'activated', false);
  newArray.push(anObj);
});

JS Fiddle

希望对您有所帮助!