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

时间:2019-02-14 17:59:10

标签: javascript vue.js vuejs2 vue-reactivity

我已经删除了代码中大部分无用的部分,所以不用担心该代码是否真的没有道理,只是为了向您展示什么不起作用。

首先,我从名为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,但是结果是相同的。

然后,我显示一些按钮以触发“激活”

<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在单击刷新时都会显示更新的值。这是一个反应性问题。

您可以在这里找到小提琴:

https://jsfiddle.net/dv1jgneb/

1 个答案:

答案 0 :(得分:1)

来自Docs

  

由于Vue在实例初始化期间执行getter / setter转换过程,因此数据对象中必须存在一个属性,以便Vue对其进行转换并使其具有反应性。

这说明了为什么只有第三个按钮“触发了东西”。

因此,您可以在data()中添加该属性,或者按照文档中的说明使用this.$set

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

JS Fiddle

希望这会有所帮助!