开发者问题收集

Vue js 比较两个对象并消除观察者中的差异

2020-08-07
4091

我的数据:

data() {
  return {
    currentStore: this.store,
    brands: [],
  }
},

我的 v-select

<v-select
    v-model="currentStore.brands.data"
    :options="allBrands"
    :taggable="true"
    :multiple="true"
/>

我有一个对象上的观察者,它看起来像这样 (this.newVal):

brands:Object
 data:Array[1]
  0:Object
    name:"3T"
 data:Array[1]
  0:Object
    name:"abc"

我想将该对象与这个 (this.allBrands) 进行比较

allBrands:Array[254]
  0:Object
    name:"3T"
  1:Object
    name:"Achielle"

正如您所见,我希望名称“abc”不在第二个对象中,我想将其从观察者中删除,这就是我所拥有的:

Object.keys(newVal).forEach(function(key) {
    console.log(Object.values(this.allBrands).includes(newVal[key].name));
});


watch: {
  "store.brands.data": function (newVal, oldVal) {
    console.log(this.allBrands);
    console.log(newVal);

    Object.keys(newVal).forEach(function(key) {
      console.log(Object.values(this.allBrands).includes(newVal[key].name));
    });
  }
},

我收到以下错误:

"TypeError: Cannot read property 'allBrands' of undefined"

我的目标是仅在我的 store.brands.data 中拥有:

brands:Object
 data:Array[1]
  0:Object
    name:"3T"

因为那是只有一个在 this.allBrands

编辑

Object.keys(newVal).forEach((key) => {
    if (!Object.values(this.allBrands).includes(newVal[key].name)) {
        newVal.pop();
    }
});

这给了我以下我不明白的错误:

Error in callback for watcher "store.brands.data": "TypeError: Cannot read property 'name' of undefined"

2个回答

根据您提到的错误, this 似乎未定义,您的方法无法找到 vue 实例

问题在于 this 与您的 function 的绑定。您需要使用 arrow fn 以词法方式绑定 this

watch: {
  "store.brands.data": function (newVal, oldVal) {
    console.log(this.allBrands);
    console.log(newVal);

要更新或删除 vue 对象的属性,我建议您使用 delete ref: https://v2.vuejs.org/v2/api/#Vue-delete

Object.keys(newVal).forEach((key) => {
      console.log(Object.values(this.allBrands).includes(newVal[key].name));
    });
  }
},
Satyam Pathak
2020-08-07

正如@Satyam Pathak 所写,第一个错误的原因是绑定问题,可以通过多种方式解决,但最现代的解决方案是使用箭头函数。

// Use of an arrow function

watch: {
  "store.brands.data": (newVal, oldVal) => { // use arrow functions in both places for consistency. 
    console.log(this.allBrands);
    console.log(newVal);

    Object.keys(newVal).forEach((key) => { // use an arrow function to bind the context to the parent context
      console.log(Object.values(this.allBrands).includes(newVal[key].name));
    });
  }
},


// Use of a constant to capture the context of the parent

watch: {
  "store.brands.data": function (newVal, oldVal) {
    const self = this;

    Object.keys(newVal).forEach(function(key) {
      console.log(Object.values(self.allBrands).includes(newVal[key].name));
    });
  }
},

// Bind the function to return a function that is bound to the parent context
watch: {
  "store.brands.data": function (newVal, oldVal) {
    Object.keys(newVal).forEach(function(key) {
      console.log(Object.values(this.allBrands).includes(newVal[key].name));
    }.bind(this));
  }
},

关于第二个问题,如果 newVal 采用以下形式

brands:Object
 data:Array[1]
  0:Object
    name:"3T"
 data:Array[1]
  0:Object
    name:"abc"

您收到错误 “TypeError:无法读取未定义的属性‘name’” 的原因是因为

Object.keys(newVal) 返回“data” 并且 newValue.data 返回一个包含对象 a 的数组。

因此 newVal.data.name 将返回错误。一种选择是循环遍历每个数组,但这不是理想的方法。

我想过很多方法来解决这个问题,但它们涉及多个 for 循环,效率低下,坦率地说,甚至不值得分享。这是一种糟糕的编码实践。

您应该考虑简化 newVal 的数据结构。例如, newVal 是一个数组对象。它可以简化为对象数组吗?

Tony
2020-08-07