watch是静态声明式追踪且默认惰性执行,watchEffect是动态运行时追踪且默认立即执行;前者需显式指定依赖和deep选项,适合高成本精确控制场景,后者自动收集依赖、天然深度监听,适合轻量联动逻辑。

依赖追踪机制不同
watch 是静态声明式追踪:你必须在第一个参数里明确写出要监听什么——可以是 ref、reactive 对象的某个属性、getter 函数,甚至数组形式的多个源。Vue 在初始化时就解析并锁定这些依赖,后续只响应它们的变化,回调中访问的其他响应式变量不会被纳入监听范围。
watchEffect 是动态运行时追踪:它不关心你“想监听谁”,而是直接执行一次传入的副作用函数,在执行过程中自动记录所有被读取的响应式值(比如 count.value、form.email、user.profile.name)。下次只要其中任意一个变化,整个函数就重跑。
触发时机与执行行为不同
watch 默认惰性执行:组件挂载时不触发,仅当监听的数据真正改变时才调用回调。如需首次渲染后立刻执行,得加 { immediate: true } 选项。
watchEffect 默认立即执行:定义即运行,先同步执行一次以收集初始依赖,之后任一依赖更新都会再次执行。这使得它天然适合初始化状态同步、实时 UI 反馈等场景。
立即学习“前端免费学习笔记(深入)”;
- watchEffect 没有新旧值参数,只能通过当前变量值反映最新状态
- watch 支持
(newVal, oldVal),便于做差异判断或清理前序操作 - watchEffect 对 reactive 对象默认深度追踪;watch 则需显式设置
{ deep: true }
适用逻辑粒度与控制精度不同
watch 更适合目标明确、高成本、需精细控制的副作用:例如搜索请求、表单提交、权限变更后的跳转。你能确保只有特定字段变化才发请求,避免因无关状态更新导致重复调用。
watchEffect 更适合轻量、联动性强、状态驱动的副作用:例如实时计算汇总值、自动保存草稿、根据多个输入动态切换验证提示。它把“哪些数据会影响这个逻辑”交由执行过程自动发现,减少手动维护依赖列表的负担。
- watchEffect 的依赖可能随条件分支动态变化(比如
if (show) console.log(data.value)),而 watch 的依赖在定义时就固定了 - watchEffect 中若意外读取了不该监听的响应式变量,会导致不必要的重执行,调试难度略高
清理与资源管理方式一致但写法不同
两者都支持副作用清理,但注册方式略有区别:
- watch 使用
onInvalidate回调(Vue 3.2+ 推荐),在新副作用即将执行前触发清理逻辑 - watchEffect 直接在副作用函数参数中接收
onInvalidate,更直观地绑定到当前执行上下文
例如异步请求未完成时被新请求覆盖,都可通过 onInvalidate 取消上一轮 pending 请求,防止状态错乱。


















