在 Vue3 中,watch和watchEffect是用于响应式监听数据变化的两个 API,它们的主要区别和适用场景如下:
核心区别
-
触发时机
watch:只监听明确指定的数据源,且只有当这些数据源变化时才会触发回调。watchEffect:会自动追踪其内部使用的所有响应式依赖,并在初始执行时立即触发一次,之后依赖变化时再次触发。
-
依赖声明方式
watch:需要显式指定要监听的数据源,可以是一个或多个响应式引用、计算属性等。watchEffect:不需要显式指定依赖,自动捕获回调函数中使用的所有响应式数据。
-
回调参数
watch:回调函数接收三个参数:新值、旧值和可选的onCleanup函数(用于清理副作用)。watchEffect:回调函数只接收一个onCleanup函数,不提供新旧值对比。
适用场景
-
watch 的适用场景
- 需要访问变化前后的值(例如计算差值、记录变更历史)。
- 监听特定数据的变化(例如表单输入、路由参数)。
- 需要延迟或异步执行副作用(例如 API 请求)。
- 需要在组件销毁时手动清理副作用(例如定时器、WebSocket 连接)。
-
watchEffect 的适用场景
- 需要根据多个响应式依赖自动触发副作用(例如自动保存表单数据)。
- 副作用不需要访问旧值(例如更新 DOM、同步本地存储)。
- 简化依赖追踪(无需显式列出所有依赖)。
示例对比
以下是一个简单的示例,展示两者的差异:
import { ref, watch, watchEffect } from 'vue'
const count = ref(0)
const double = computed(() => count.value * 2)
// watch示例:监听count变化
watch(count, (newValue, oldValue) => {
console.log(`count从${oldValue}变为${newValue}`)
// 可以访问新旧值进行比较
})
// watchEffect示例:自动追踪所有依赖
watchEffect(() => {
console.log(`count或double变化了:${count.value}, ${double.value}`)
// 不需要显式声明依赖,只要内部使用的响应式数据变化就会触发
})
// 修改count值
count.value++ // 同时触发watch和watchEffect
总结
- 使用 watch:当需要精确控制监听的数据源,并需要访问变化前后的值时。
- 使用 watchEffect:当需要自动响应所有依赖的变化,且不需要新旧值对比时。
最后,以官方文档清晰的说明来结尾:
选择合适的 API 可以使代码更清晰、更高效,避免不必要的副作用触发。