VueJS深度观察器-多个对象上的特定属性

时间:2019-06-12 16:19:35

标签: javascript vue.js vuejs2 watch

问题

我有一个带有多个对象的“产品”数组。每个产品对象都包含属性“价格”。我想在每个产品中观看此属性以进行可能的更改。当用户在输入框中更改价格时,我用它来计算佣金价格。

我的产品数组如下:

[
  0: {
    name: ...,
    price: ...,
    commission: ...,
  },
  1: {
    name: ...,
    price: ...,
    commission: ...,
  },
  2: {
    name: ...,
    price: ...,
    commission: ...,
  },
  ...
  ...
  ...
]

我的代码

我已经尝试过了,但是除了第一次加载产品时,它没有检测到任何更改;

    watch  : {
        // Watch for changes in the product price, in order to calculate final price with commission
        'products.price': {
            handler: function (after, before) {
                console.log('The price changed!');
            },
            deep   : true
        }
    },

这样加载产品;

mounted: async function () {
            this.products = await this.apiRequest('event/1/products').then(function (products) {
                // Attach reactive properties 'delete' & 'chosen' to all products so these can be toggled in real time
                for (let product of products) {
                    console.log(product.absorb);
                    Vue.set(product, 'delete', false);
                    Vue.set(product, 'chosen', product.absorb);
                }

                console.log(products);

                return products;
            })
        }

我看过的其他问题 Vue.js watching deep properties 这是试图监视尚不存在的属性。 VueJs watching deep changes in object 这个正在监视其他组件的变化。

1 个答案:

答案 0 :(得分:1)

您不能真正观察products.price,因为价格是单个产品的属性,而不是产品数组的属性。

声明性观察者对数组有问题,如果您尝试在监视表达式中使用索引,例如products[0].price,则会收到来自Vue的警告

  

[Vue警告]:观看路径失败:“产品[0]。价格”。 Watcher仅接受简单的点分隔路径。要完全控制,请改用函数。

这意味着您可以将programmatic watch与一个函数一起使用,但并不能很好地解释它。

这是在您的情况下实现此目标的一种方法

<script>
export default {
  name: "Products",
  data() {
    return {
      products: []
    };
  },
  mounted: async function() {
    this.products = await this.apiRequest('event/1/products')...

    console.log("After assigning to this.products", this.products);

    // Add watchers here, using a common handler
    this.products.forEach(p => this.$watch(() => p.price, this.onPriceChanged) );

    // Simulate a change
    setTimeout(() => {
      console.log("Changing price");
      this.products[0].price= 100;
    }, 1000);
  },
  methods: {
    onPriceChanged(after, before) {
      console.log(before, after);
    }
  }
};
</script>

这是我的测试Codesandbox(我使用颜色而不是价格,因为测试api中没有价格)