在vue3中watch与watchEffect的区别和作用是什么

在Vue3中,watch和watchEffect都是用于响应式数据的监控和处理的API。虽然它们有相似的作用,但是它们之间还是有很大的区别的。

一、watch的基本用法

watch的基本用法是监控一个特定的数据源,当该数据源发生变化时,触发相应的回调函数。watch在Vue2中也是非常重要的API之一,它可以用来监控组件内部的数据变化,或者是监控Vuex中的数据变化。在Vue3中,watch的用法和Vue2基本一致,但是在内部实现上,Vue3采用了新的API来实现。

watch的基本语法如下:

watch(
  // 监听的数据源
  source: string | Function | Array<string | Function>,
  // 回调函数
  callback: Function,
  // 选项
  options?: WatchOptions
): WatchStopHandle

其中,source可以是一个字符串,表示要监听的数据源,也可以是一个函数,表示要监听的计算属性或者是方法。当source是一个数组时,表示同时监听多个数据源。callback是当数据源发生变化时,要执行的回调函数。options是可选的选项参数,可以用来控制watch的行为。WatchStopHandle是一个函数,用来取消watch的监听。

下面是一个简单的例子,演示了如何使用watch来监控组件内部的数据变化:

<template>
  <div>
    <input v-model="message" />
    <p>{{ message }}</p>
  </div>
</template>

<script>
import { watch } from 'vue'

export default {
  data() {
    return {
      message: 'Hello, World!'
    }
  },
  created() {
    watch(
      // 监听数据源
      () => this.message,
      // 回调函数
      (newValue, oldValue) => {
        console.log(`message发生变化:${oldValue} => ${newValue}`)
      }
    )
  }
}
</script>

在这个例子中,我们使用watch来监听组件内部的message数据变化。当message的值发生变化时,控制台会输出相应的信息。需要注意的是,watch只能在组件实例被创建之后才能使用。

二、watch的高级用法

除了基本用法之外,watch还有一些高级用法,可以用来处理更加复杂的数据变化场景。

  1. 深度监听

当我们需要监听一个复杂的对象或者是数组时,可能需要对其进行深度监听。Vue3中提供了deep选项来实现深度监听。例如:

data() {
  return {
    user: {
      name: '张三',
      age: 18,
      address: {
        province: '广东',
        city: '深圳'
      }
    }
  }
},
watch: {
  user: {
    deep: true,
    handler(newValue, oldValue) {
      console.log('user发生变化', newValue, oldValue)
    }
  }
}

在这个例子中,我们使用了deep选项来实现对user对象的深度监听。当user对象的任意属性发生变化时,都会触发watch的回调函数。

需要注意的是,深度监听会对性能产生一定的影响,所以在使用时需要谨慎。

  1. 监听多个数据源

当我们需要监听多个数据源时,可以使用watch的数组语法来实现。例如:

data() {
  return {
    message: 'Hello, World!',
    count: 0
  }
},
watch: {
  [message, count]: {
    handler(newValue, oldValue) {
      console.log('message或count发生变化', newValue, oldValue)
    }
  }
}

在这个例子中,我们使用了数组语法来同时监听message和count两个数据源。当message或count的值发生变化时,都会触发watch的回调函数。

需要注意的是,数组语法只能在Vue3中使用,Vue2中不支持。

  1. 监听异步数据

当我们需要监听异步数据时,可以使用watch的immediate选项来实现。例如:

data() {
  return {
    message: ''
  }
},
watch: {
  message: {
    immediate: true,
    handler(newValue, oldValue) {
      console.log('message发生变化', newValue, oldValue)
    }
  }
},
methods: {
  async fetchData() {
    const data = await fetch('/api/data')
    this.message = data.message
  }
}

在这个例子中,我们使用了immediate选项来实现对异步数据的监听。当message的值在组件创建之后第一次被赋值时,也会触发watch的回调函数。

需要注意的是,immediate选项只有在watch监听的数据源发生变化时才会触发,如果数据源一开始的值就是undefined或null等假值,immediate选项是不会触发的。

三、watchEffect的基本用法

watchEffect是Vue3中新增的API,它可以用来监听响应式数据的变化,并在数据变化时自动执行相应的回调函数。

watchEffect的基本语法如下:

watchEffect(
  // 回调函数
  effect: (onInvalidate: InvalidateCbRegistrator) => void,
  // 选项
  options?: WatchEffectOptions
): WatchStopHandle

其中,effect是一个回调函数,当watchEffect监听的数据源发生变化时,就会执行这个回调函数。onInvalidate是用来取消watchEffect监听的回调函数。options是可选的选项参数,可以用来控制watchEffect的行为。WatchStopHandle是一个函数,用来取消watchEffect的监听。

下面是一个简单的例子,演示了如何使用watchEffect来监听响应式数据的变化:

<template>
  <div>
    <input v-model="message" />
    <p>{{ message }}</p>
  </div>
</template>

<script>
import { watchEffect } from 'vue'

export default {
  data() {
    return {
      message: 'Hello, World!'
    }
  },
  created() {
    watchEffect(() => {
      console.log(`message发生变化:${this.message}`)
    })
  }
}
</script>

在这个例子中,我们使用watchEffect来监听组件内部的message数据变化。当message的值发生变化时,控制台会输出相应的信息。

需要注意的是,watchEffect可以在组件实例创建之前使用,而且它可以自动识别依赖的响应式数据,所以我们不需要额外指定要监听的数据源。

四、watch和watchEffect的区别

虽然watch和watchEffect都是用来监听响应式数据的变化,但是它们之间还是有很大的区别的。

  1. 监听粒度不同

watch的监听粒度比较细,我们需要手动指定要监听的数据源,当数据源发生变化时,才会触发watch的回调函数。而watchEffect的监听粒度比较粗,它可以自动识别依赖的响应式数据,当任意一个依赖的响应式数据发生变化时,就会触发watchEffect的回调函数。

  1. 执行时机不同

watch是在watch监听的数据源发生变化时,才会执行回调函数。而watchEffect是在watchEffect创建之后立即执行回调函数,然后自动识别依赖的响应式数据,当任意一个依赖的响应式数据发生变化时,就会再次执行回调函数。

  1. 选项不同

watch的选项比较丰富,可以控制watch的行为,例如深度监听、异步监听、多数据源监听等。而watchEffect的选项比较简单,只有一个选项,可以控制watchEffect的行为。

需要注意的是,在使用watch和watchEffect时,我们需要注意一些事项:

  1. 不要在watch或watchEffect内部修改监听的数据源,否则会陷入死循环。
  2. 不要在watchEffect内部使用非响应式数据,否则会导致无法正确识别依赖。
  3. 不要在watchEffect内部使用异步代码,否则会导致无法正确识别依赖。
  4. 谨慎使用深度监听,因为它会对性能产生一定的影响。

总之,watch和watchEffect是Vue3中非常重要的API之一,它们可以用来监听响应式数据的变化,并在数据变化时执行相应的回调函数。在使用时,我们需要根据具体的业务场景,选择合适的API,并注意一些事项,以保证代码的正确性和性能。