VueJS 深度观察者 - 特定于多个对象 属性

VueJS deep watcher - specific property on multiple objects

问题

我有一个包含多个对象的 "products" 数组。每个产品对象都包含 属性 "price"。我想在每个产品中查看此 属性 以了解可能的更改。当用户在输入框中更改价格时,我使用它来计算佣金价格。

我的产品数组如下所示;

[
  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;
            })
        }

我看过的其他问题 这个正在尝试观看尚不存在的 属性。 这个正在监视另一个组件的变化。

你不能真的 deep-watch products.price,因为价格是单个产品的 属性,而不是产品数组。

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

[Vue warn]: Failed watching path: “products[0].price”. Watcher only accepts simple dot-delimited paths. For full control, use a function instead.

这意味着您可以将 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)