跳到主要内容

🧠 Vue watch vs watchEffect 全面对比

🎯 一句话区别(面试口语版)

watch 更像是“观察一个明确的数据源”,而 watchEffect 是“自动收集依赖,只要访问了响应式数据就会触发”。


✅ 一、定义与语法

特性watchwatchEffect
是否自动收集依赖❌ 否,需显式指定依赖源✅ 是,自动追踪同步访问的响应式依赖
主要用途响应某个特定数据源的变化,常用于副作用(如请求)处理副作用逻辑,自动追踪依赖
回调参数(newVal, oldVal, onCleanup)(onCleanup)(不能拿到 new/old 值)
支持懒执行✅ 默认懒执行,immediate: true 可立即执行❌ 默认立即执行
可用于异步逻辑✅ 支持良好,结合 onCleanup() 使用✅ 支持良好,适合轻量副作用逻辑
清理副作用onCleanup(fn)onCleanup(fn)

✅ 二、使用示例对比

watch 示例(显式依赖):

watch(() => props.id, (newVal, oldVal) => {
fetchData(newVal)
})

watchEffect 示例(自动依赖):

watchEffect(() => {
fetchData(props.id) // 只要 props.id 改变就重新执行
})

✅ 三、依赖收集机制

特性watchwatchEffect
响应式追踪范围只追踪 getter 函数的返回值追踪函数体内同步访问的所有响应式数据
支持深层调用链✅,getter 中访问深层响应式数据会被追踪✅,只要访问了响应式数据就会被追踪
异步代码内访问响应式❌ 不追踪❌ 不追踪

✅ 四、典型应用场景

🔹 watch 适用场景:

  • 明确监听某个响应式值,如:props、路由参数等
  • 希望拿到 newVal / oldVal
  • 想要懒触发副作用,或手动控制执行时机

🔹 watchEffect 适用场景:

  • 响应式数据可能有多个来源
  • 快速实现响应式副作用,如自动 fetch、同步 DOM
  • 更像是 computed + watch 的组合

✅ 五、陷阱 & 注意事项

情况watchwatchEffect
异步中访问响应式值不会被追踪❗ 不会❗ 不会
改变的值是深层对象字段需要 deep: true自动追踪,除非被异步隔开
第一次是否执行默认不执行,需配置默认立即执行
cleanup 清理副作用的时机下一次执行前或组件卸载同左

✅ 六、实现原理(进阶可选)

  • watch 通过传入一个 getter 显式收集依赖(只追踪返回值)
  • watchEffect 在执行时设置一个全局 activeEffect,在同步函数体中访问的响应式数据会调用 track() 自动建立依赖关系
  • 响应式数据本质是用 Proxy 拦截 get,判断是否存在 activeEffect,如果有就记录进依赖集合

✅ 七、最终总结口诀(面试可背)

watch 明确依赖、懒执行,适合特定字段;watchEffect 自动依赖、立即执行,适合响应式副作用。