Vue.js - 观察对象的特定属性并在更改时加载数据

ven*_*nom 10 javascript watch vue.js vuejs2

我有一个带有名为 prop 的 Vue 组件product,它是一个具有一堆属性的对象。而且它经常变化。

export default {
    props: {
        product: {
            type: Object,
            default: () => {},
        },
    },
    watch: {
        'product.p1'() {
            this.loadData()
        },
        'product.p2'() {
            this.loadData()
        },
    },
    methods: {
        loadData() {
            doApiRequest(this.product.p1, this.product.p2)
        }
    },
}
Run Code Online (Sandbox Code Playgroud)

p1当仅属性和p2of product发生更改时,组件应加载新数据。一种方法是观察整个产品并在更改时加载数据。但它会产生不必要的请求,因为p1p2可能没有改变。

另一个想法是 watchproduct.p1product.p2,并调用相同的函数在每个观察器中加载数据。但有可能在新版本的产品中两者p1都发生了变化,会触发2次调用。p2

使用去抖函数进行数据加载会是一个好的解决方案吗?

或者更确切地说,对整体使用单个观察程序product,并将新的p1p2字符串化的版本与旧的字符串化版本进行比较,以确定是否应该触发数据加载?

Dec*_*oon 2

有几种方法可以实现这一点,每种方法都有优点和缺点。

我所做的一种简单方法是使用监视函数来访问您想要监视的每个属性,然后返回一个新的空对象。Vue 知道product.p1product.p2在 watch 函数中被访问,因此只要这些属性发生变化,它就会重新执行它。然后,通过从 watch 函数返回一个新的空对象实例,Vue 将触发 watch 处理程序,因为 watch 函数返回了一个新值(因此正在监视的内容“发生了变化”)。

created() {
  this.$watch(() => {
    // Touch the properties we want to watch
    this.product.p1;
    this.product.p2;

    // Return a new value so Vue calls the handler when
    // this function is re-executed
    return {};
  }, () => {
    // p1 or p2 changed
  })
}
Run Code Online (Sandbox Code Playgroud)

优点:

  • 您不必对任何内容进行字符串化。
  • 您不必对手表处理函数进行反跳操作。

缺点:

  • 您无法跟踪p1和的先前值p2
  • 请注意是否this.product可能为空/未定义。
  • p1当或p2改变时总会触发;即使p1p2在下一个微任务之前设置回之前的值(即$nextTick());但在大多数情况下这不太可能成为问题。
  • 你需要使用this.$watch(). 如果您想使用该watch选项,那么您需要监视计算属性。

无论如何,其中一些缺点也适用于其他方法。

更紧凑的版本是:

this.$watch(
  () => (this.product.p1, this.product.p2, {}),
  () => {
    // changed
  }
})
Run Code Online (Sandbox Code Playgroud)