Vue计算出的问题-什么时候会再次计算

时间:2019-02-23 12:53:46

标签: javascript vue.js

Vue计算值已经使我困惑了一段时间

何时会再次计算

condition1:

data() {
  return {
    cart:{
      item:{
        nums: 10,
        price: 10
      }
    }
  };
},
computed: {
  total() {
    return this.cart.item.nums * this.cart.item.price
  }
},
methods:{
  set(){
    this.cart.item = {
       nums: 5,
       price: 5
    }
  }
}

计算即可使用


condition2:

data() {
  return {
    cart: [{
        nums: 10,
        price: 10
    }]
  };
},
computed: {
  total() {
    return this.cart[0].nums * this.cart[0].price
  }
},
methods:{
  set(){
    this.cart[0] = {
       nums: 5,
       price: 5
    }
  }
}

计算无法正常工作


我知道这是解决方案,但是为什么呢?

methods:{
  set(){
    this.cart[0].nums = 5
    this.cart[0].price = 5
    }
  }
}

为什么在condition2中没有看到它?

为什么Vue不想被观察?

1 个答案:

答案 0 :(得分:6)

与对象和数组的反应性对Vue有点挑剔。使用其他变量,很容易检测到它们何时被更改,但是对于对象和数组,并非总是能够检测到对象/数组中的某些内容何时发生了更改。 (也就是说,没有代理,它将出现在Vue 3.x中)

在您的情况下,如果将total标记为已更改,this.cart被标记为已更改或者this.cart[0]this.cart[0].nums被更改,this.cart[0].price将重新计算。问题是您要替换this.cart[0]中的对象。这意味着this.cart[0].pricenums不会更改,因为它们仍然指向旧对象。显然,this.cart[0]this.cart未被标记为已更改,因此Vue仍然认为total是最新的。

有几种方法可以解决此问题。一种是使用Vue的辅助方法来处理对象/数组,即Vue.setVue.delete。您可以使用this.$setthis.$delete在SFC中访问它们。 this.$set明确将您作为第一个参数传递的内容标记为“更改”,因此您的总数也将被更新。

this.$set(this.cart, 0, {
  nums: 2,
  price: 100
});

另一种方法是修改对象本身,而不是替换它。由于您仍在使用同一对象,因此Vue将检测到this.cart[0]已更改。

setItem() {
  this.cart[0] = Object.assign(
    this.cart[0],
    {
      nums: 5,
      price: 5
    }
  );
}

另一种方法是使用许多数组方法之一。在您的情况下,可以使用Array.prototype.splice。由于这是一个函数调用,因此Vue可以检测到该函数已被调用,并且可以将正确的项目标记为已更改,这将触发依赖它的所有内容的更新。

this.cart.splice(0, 1, {
  nums: 50,
  price: 10
});

Edit Vue + Vuex + VueRouter template