在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还有一些高级用法,可以用来处理更加复杂的数据变化场景。
- 深度监听
当我们需要监听一个复杂的对象或者是数组时,可能需要对其进行深度监听。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的回调函数。
需要注意的是,深度监听会对性能产生一定的影响,所以在使用时需要谨慎。
- 监听多个数据源
当我们需要监听多个数据源时,可以使用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中不支持。
- 监听异步数据
当我们需要监听异步数据时,可以使用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都是用来监听响应式数据的变化,但是它们之间还是有很大的区别的。
- 监听粒度不同
watch的监听粒度比较细,我们需要手动指定要监听的数据源,当数据源发生变化时,才会触发watch的回调函数。而watchEffect的监听粒度比较粗,它可以自动识别依赖的响应式数据,当任意一个依赖的响应式数据发生变化时,就会触发watchEffect的回调函数。
- 执行时机不同
watch是在watch监听的数据源发生变化时,才会执行回调函数。而watchEffect是在watchEffect创建之后立即执行回调函数,然后自动识别依赖的响应式数据,当任意一个依赖的响应式数据发生变化时,就会再次执行回调函数。
- 选项不同
watch的选项比较丰富,可以控制watch的行为,例如深度监听、异步监听、多数据源监听等。而watchEffect的选项比较简单,只有一个选项,可以控制watchEffect的行为。
需要注意的是,在使用watch和watchEffect时,我们需要注意一些事项:
- 不要在watch或watchEffect内部修改监听的数据源,否则会陷入死循环。
- 不要在watchEffect内部使用非响应式数据,否则会导致无法正确识别依赖。
- 不要在watchEffect内部使用异步代码,否则会导致无法正确识别依赖。
- 谨慎使用深度监听,因为它会对性能产生一定的影响。
总之,watch和watchEffect是Vue3中非常重要的API之一,它们可以用来监听响应式数据的变化,并在数据变化时执行相应的回调函数。在使用时,我们需要根据具体的业务场景,选择合适的API,并注意一些事项,以保证代码的正确性和性能。