watch 和 watchEffect 都是监听器,有很多相同点,也有些不同点。
一、相同点
1、都可以监听数据的变化
import {ref, reactive, watch, watchEffect} from 'vue'
export default {
setup() {
const stateRef = ref(0)
const stateReactive = reactive({num: 0})
watch(stateRef, (newValue, oldValue) => {
console.log('原始值:', oldValue)
console.log('新值:', newValue)
})
watch(() => stateReactive.num, (newValue, oldValue) => {
console.log('原始值:', oldValue)
console.log('新值:', newValue)
})
watchEffect(() => {
console.log(stateRef.value)
console.log(stateReactive.num)
})
}
}
2、都可以通过 stop 手动停止侦听
import {ref, watch, watchEffect} from 'vue'
export default {
setup() {
const stateRef = ref(0)
const stop1 = watch(stateRef, (newValue, oldValue) => {
//...
})
stop1();
const stop2 = watchEffect(() => {
//...
})
stop2();
}
}
3、都可以清除副作用,接收一个 onInvalidate
函数作入参,用来注册清理失效时的回调。
import {ref, watch, watchEffect} from 'vue'
export default {
setup() {
const stateRef = ref(0)
watch(stateRef, (newValue, oldValue, onInvalidate) => {
const token = performAsyncOperation(stateRef.value)
onInvalidate(() => {
token.cancel();
})
})
watchEffect(onInvalidate => {
const token = performAsyncOperation(stateRef.value)
onInvalidate(() => {
token.cancel();
})
})
}
}
4、相同的副作用刷新时机
Vue 的响应性系统会缓存副作用函数,并异步地刷新它们,这样可以避免同一个“tick” 中多个状态改变导致的不必要的重复调用。当一个用户定义的副作用函数进入队列时,默认情况下,会在所有的组件 update
前执行
二、不同点
1、watchEffect 不需要手动传入依赖,实现了响应式状态的自动应用。
2、watchEffect 在每次初始化时会执行一次回调函数来自动获取依赖。而 watch 在默认情况下是惰性的,只有当被侦听的源发生变化时才执行回调。
3、watchEffect 不能获取到原值,只能获取到变化后的值。