在 Vue 3 中,watch
和 watchEffect
都是用于侦听数据变化并执行相应的副作用(side effects),但它们之间存在一些关键区别:
watch
- 显式指定监听的数据源:你需要明确指出要监听的响应式数据(如 ref 或 reactive 对象的属性)。
- 惰性执行:只有当被监听的数据发生变化时,回调函数才会被执行。首次创建 watcher 实例时不会立即执行回调。
- 提供旧值和新值:在回调函数中,你可以访问到被监听数据的旧值和新值,这对于需要比较前后状态的场景非常有用。
- 更灵活的配置选项:支持更多的选项,比如深度监听 (
deep
)、一次性监听 (immediate
) 等。
示例:
import { ref, watch } from 'vue';const count = ref(0);watch(count, (newVal, oldVal) => {console.log(`count changed from ${oldVal} to ${newVal}`);
});count.value++; // 输出: count changed from 0 to 1
watchEffect
- 自动收集依赖:不需要显式指定监听哪些数据源,它会自动追踪在回调函数内部访问的所有响应式数据,并对这些数据进行监听。
- 立即执行一次:除了监听数据的变化外,还会在初次运行时立即执行一次以捕获当前状态。
- 仅提供当前值:只提供当前值给回调函数,不提供旧值。
- 更适合副作用管理:由于其自动追踪依赖的特性,非常适合于处理那些依赖多个响应式数据的情况。
示例:
import { ref, watchEffect } from 'vue';const count = ref(0);watchEffect(() => {console.log(`count is: ${count.value}`);
});count.value++; // 输出: count is: 1
总结
-
使用
watch
当你需要:- 明确地监听一个或多个特定的数据源。
- 访问旧值和新值。
- 利用更高级的监听选项,如深度监听或立即执行。
-
使用
watchEffect
当你希望:- 自动处理依赖关系而无需手动声明。
- 在初始化时立即执行副作用,并在依赖项变化时重新执行。
- 关注当前状态而非历史变化。
两者各有优势,选择哪一种取决于你的具体需求和偏好。