Q:文档写的 watch会避免发生副作用时追踪依赖。 watchEffect会在副作用发生期间追踪依赖 怎么理解
A:
Vue 文档中关于 watch vs watchEffect 的依赖追踪时机差异 的描述,非常关键,下面我帮你深度解析这个区别。
📘 Vue 文档原意(概括):
• watch:在副作用触发前就确定了依赖。你显式指定监听哪个响应式变量,它不会动态收集依赖。
• watchEffect:副作用函数运行的时候才动态收集依赖。你不用指定变量,Vue 会自动收集在副作用函数中读取的响应式属性。
🔍 举个例子来直观理解
🌿 watch 示例
const a = ref(1);
const b = ref(2);
watch(a, () => {
console.log(b.value); // 虽然访问了 b,但 watch 只追踪 a
});
✔️ 这里你只监听了 a,即使你在回调中用了 b,b 的变化不会触发 watch 再次执行。
👉 因为 watch 是在副作用函数运行前就决定监听哪些依赖的(即你指定的 a),它不会在副作用执行时追踪新的依赖。
🌿 watchEffect 示例
watchEffect(() => {
console.log(a.value);
console.log(b.value);
});
✔️ 这里 Vue 会在运行这个副作用函数的时候,自动追踪 a 和 b 的读取操作。
👉 所以只要 a 或 b 任意一个变了,副作用函数就会重新执行。
🎯 核心对比总结
特性 watch watchEffect
依赖来源 显式指定 自动收集(运行时读取)
追踪时机 副作用执行前决定依赖 副作用执行期间决定依赖
灵活性 更明确、可控 更智能、自动化
适合场景 精确监听一个/多个值,获取旧值等 快速绑定响应式依赖,处理副作用(API、DOM操作等)
⚠️ 实际应用场景示例对比
用 watch:
watch([a, b], ([newA, newB]) => {
// 只有 a 和 b 的变化会触发
// 可对比 oldValue / newValue
});
用 watchEffect:
watchEffect(() => {
// Vue 自动追踪 a、b 的访问
if (a.value > 5) {
console.log(b.value);
}
});
✔️ 上面 watchEffect 会根据你运行时访问的路径自动收集依赖,比如你只有在 a.value > 5 的时候才访问 b.value,Vue 也能动态追踪到这个路径。
🧠 结论一句话:
watch 是「事先告诉 Vue:我要监听谁」,
watchEffect 是「你运行的时候访问了谁,Vue 就监听谁」。