Vue计算问题 - 何时再次计算

Bil*_*320 3 javascript vue.js

Vue计算已经困扰了我一段时间

什么时候会再次计算

条件1:

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
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

计算将工作


条件2:

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
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

计算不起作用


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

methods:{
  set(){
    this.cart[0].nums = 5
    this.cart[0].price = 5
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

为什么不在条件2中观察到它?

为什么Vue不希望被观察到?

Sum*_*ai8 7

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

在您的情况下,total如果this.cart标记为已更改,this.cart[0]标记为已更改this.cart[0].numsthis.cart[0].price已更改或已更改,则将重新计算.问题是你要更换对象this.cart[0].这意味着this.cart[0].price并且nums不会改变,因为那些仍然指向旧对象.显然,this.cart[0]this.cart没有标记为已更改,因此Vue仍然认为total是最新的.

有几种方法可以解决这个问题.一种是使用Vue公司的辅助方法与对象/数组,即工作Vue.set,Vue.delete.您可以使用this.$set或在SFC中访问它们this.$delete.当this.$set明确标记您作为第一个参数传递的任何内容为"已更改"时,您的总数也将更新.

this.$set(this.cart, 0, {
  nums: 2,
  price: 100
});
Run Code Online (Sandbox Code Playgroud)

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

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

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

this.cart.splice(0, 1, {
  nums: 50,
  price: 10
});
Run Code Online (Sandbox Code Playgroud)

编辑Vue + Vuex + VueRouter模板