返回

深入剖析 Vue 中 watch/computed/生命周期的执行顺序

前端

在 Vue.js 的响应式系统中,理解 watchcomputed 和生命周期的执行顺序至关重要。这些机制共同协作,确保数据变化时组件的响应行为正确且高效。

生命周期复习

创建阶段

  • beforeCreate :最早创建阶段,此时实例还未创建,不能访问 this
  • created :实例创建完毕,可以访问 this,但尚未挂载到 DOM。
  • mounted :组件已挂载到 DOM 中,此后 DOM 操作和事件监听生效。

更新阶段

  • beforeUpdate :组件更新之前,计算属性未更新,DOM 也未更新。
  • updated :组件更新完毕,计算属性和 DOM 均已更新。

watchcomputed

watch

watch 允许我们在数据发生变化时执行特定的动作。其语法如下:

watch: {
  foo(newVal, oldVal) {
    // 数据变化时触发的回调
  }
}

computed

computed 允许我们从其他数据属性中派生计算属性。其语法如下:

computed: {
  foo() {
    // 返回派生数据的计算函数
  }
}

执行顺序

watch/computed vs 生命周期

创建阶段watchcomputed 的执行顺序如下:

  1. beforeCreate 生命周期钩子
  2. created 生命周期钩子
  3. watch 观察者
  4. computed 属性计算
  5. mounted 生命周期钩子

watch/computed 相互之间

更新阶段 ,当数据发生变化时,watchcomputed 的执行顺序如下:

  1. beforeUpdate 生命周期钩子
  2. watch 观察者(按声明顺序执行)
  3. computed 属性计算(按依赖顺序执行)
  4. updated 生命周期钩子

实战案例

考虑以下 Vue 组件:

<template>
  <p>{{ message }}</p>
  <button @click="changeMessage">Change Message</button>
</template>

<script>
export default {
  data() {
    return {
      message: 'Hello World'
    }
  },
  methods: {
    changeMessage() {
      this.message = 'Goodbye World'
    }
  },
  watch: {
    message(newVal) {
      console.log(`Message changed to: ${newVal}`)
    }
  },
  computed: {
    reversedMessage() {
      return this.message.split('').reverse().join('')
    }
  }
}
</script>

当用户点击按钮时,执行顺序如下:

  1. changeMessage 方法调用。
  2. message 数据发生变化。
  3. watch 观察者执行,打印新消息。
  4. computed 属性 reversedMessage 重新计算。
  5. updated 生命周期钩子执行。

注意事项

  • watch 观察者总是优先于 computed 属性执行。
  • computed 属性会根据其依赖关系重新计算。如果 watch 观察者修改了 computed 属性依赖的数据,则 computed 属性也将重新计算。
  • 避免在 watchcomputed 中进行耗时的操作,因为这会影响组件的性能。

总结

深入了解 watchcomputed 和生命周期的执行顺序对于编写高效且响应迅速的 Vue 组件至关重要。通过遵循正确的执行顺序,我们可以确保组件在数据变化时以预期的方式更新和响应。