选 watch 还是 watcheffect,关键看是否需明确控制监听目标和获取旧值:需新旧值对比或精准触发时用 watch;依赖分散、初始化即执行、逻辑以副作用为中心时用 watcheffect。

选 watch 还是 watchEffect,关键看你要不要“明确控制监听目标”和“拿到旧值”。
需要新旧值对比或精准触发时,用 watch
比如搜索框输入后只在关键词真正变化时发请求,或表单校验中判断前后状态差异:
- 监听单个 ref,回调能接收
(newVal, oldVal),方便做条件过滤(如忽略空值、重复值) - 监听多个数据源时,数组解构可分别拿到新旧值组,适合联动逻辑(如数量+单价变动才重算总价)
- 监听 reactive 对象的某个属性,必须用 getter 函数(
() => state.name),避免盲目 deep 监听影响性能
依赖分散、初始化就要执行、逻辑以副作用为中心时,用 watchEffect
比如页面加载时自动拉取数据,或多个响应式变量共同影响一个 DOM 状态:
- 函数内用到的所有 ref / reactive 属性都会被自动追踪,不用逐个列出来
- 定义即执行——组件挂载时立刻运行一次,适合初始化逻辑(如首次获取用户信息)
- 写法更紧凑,尤其当计算逻辑涉及多个响应式变量(如
count + name + loading共同决定按钮状态)
要注意的边界情况
有些场景看似适合 watchEffect,但容易踩坑:
- 如果函数里访问了非响应式变量(比如普通 const 或 props 的非响应式字段),它不会被追踪,变化也不会触发重跑
- 无法直接知道是哪个依赖变了,调试时不如 watch 清晰;若需区分来源,还是显式用 watch 更稳妥
- watchEffect 默认不支持 deep 监听嵌套对象属性,要监听深层变化仍得靠 watch 配合
{ deep: true }
一句话决策路径
想清楚两个问题:
→ 是不是必须知道“从什么变成什么”?是 → 选 watch。
→ 是不是希望“只要相关数据一动,这段逻辑就自动重来”,且代码越少越好?是 → 选 watchEffect。










