返回

为什么组件 watch props 根据 v-if 动态判断并挂载 DOM 的做法是错误的?

前端

在 Vue.js 中,我们经常使用 watch 属性来监视组件 prop 的变化,并在 prop 变化时执行某些操作。然而,当我们使用 v-if 动态地判断组件是否挂载时,watch prop 的行为就会变得复杂。

让我们以一个示例来说明这个问题:

<template>
  <div v-if="showComponent">
    <component :prop="propValue" @update="onUpdate" />
  </div>
</template>

<script>
export default {
  data() {
    return {
      showComponent: false,
      propValue: 'initial value',
    };
  },
  watch: {
    propValue(newValue) {
      // 在 propValue 变化时执行某些操作
    },
  },
  methods: {
    onUpdate(newValue) {
      // 在组件更新时执行某些操作
    },
  },
};
</script>

在这个示例中,showComponent prop 决定了组件是否挂载。当 showComponent 为 true 时,组件会被挂载并 watch prop propValue 的变化。但是,当 showComponent 为 false 时,组件会被卸载,watch prop 也会被停止。

这意味着,当 showComponent 从 false 变为 true 时,组件会被重新挂载,并且 watch prop propValue 也会重新开始监听。然而,由于组件是重新挂载的,因此 propValue 的初始值将是 initial value,而不是上一次更新的值。

这会导致 watch prop 无法正常工作,因为它的初始值与上一次更新的值不一致。因此,我们不应该在 v-if 动态判断组件是否挂载时使用 watch prop。

为了解决这个问题,我们可以使用 watchEffect 钩子,它会在组件渲染完成后立即执行,并且不会受到 v-if 的影响。

<script>
export default {
  // ...

  watchEffect() {
    if (this.showComponent) {
      // 在 propValue 变化时执行某些操作
    }
  },
};
</script>

这样,无论 showComponent 的值如何变化,watchEffect 钩子都会在组件渲染完成后执行,确保 watch prop 能够正常工作。