Vue中的watch和watchEffect

Vue 中两个侦听副作用 API 的区别、使用场景与边界。

#tech / dev / frame #resource / vue3 #type / concept #status / growing

[!info] related notes

Vue中的watch和watchEffect

watchwatchEffect 都用于响应状态变化后的副作用,但它们对依赖的声明方式不同。

一句话定义

  • watch 是显式监听
  • watchEffect 是自动收集依赖

为什么这组 API 容易被误用

因为很多人会把:

  • 派生状态
  • 副作用
  • 自动更新

这三件事混成一件事。

但更稳的边界应该是:

  • 要“得到一个值”优先想 computed
  • 要“在变化后做点事”才考虑 watch / watchEffect

watch 的特点

  • 监听源明确
  • 可以拿到新值和旧值
  • 更适合精确控制触发条件
watch(count, (newVal, oldVal) => {
  console.log(newVal, oldVal)
})

watchEffect 的特点

  • 会立即执行一次
  • 自动收集回调中访问到的响应式依赖
  • 更适合快速声明一段响应式副作用
watchEffect(() => {
  console.log(count.value)
})

什么时候用 watch

  • 需要拿到 oldValue
  • 只想监听特定来源
  • 你要做请求、同步、日志、持久化等副作用

什么时候用 watchEffect

  • 依赖比较分散,不想手写依赖源
  • 快速建立一个自动同步的副作用
  • 这段逻辑天然应该先执行一次

一个更直观的对照

watch 更像:

  • 我知道我要盯谁
  • 我想精确控制监听来源

watchEffect 更像:

  • 你帮我自动收集回调里访问到的依赖
  • 我更关心“这段副作用和哪些响应式值有关”

和 React 的一个关键差异

如果对照 React:

  • watchEffect 有点像自动依赖收集版本的副作用
  • React 的 useEffect 更强调手写依赖数组

这也是很多人从 Vue 切到 React 时,最容易在 effect 依赖上踩坑的原因。

computed 的边界

如果你只是想推导一个值,优先用 vue-computed;只有当你真的要“在变化后做点事”,才进入 watch / watchEffect

和更新流程的关系

它们通常不是直接负责渲染本身,而是挂在响应式变化之后,处理渲染之外的副作用。

常见误区

  • 用侦听器保存本来可以直接 computed 的值
  • 在回调里反复修改监听源自己,造成循环触发
  • 把副作用和渲染逻辑混在一起

最短记忆方式

  • watch:我知道我要盯谁
  • watchEffect:你帮我收集依赖

面试要点

来自 vue-watch-vs-watch-effect-interview-question 的面试视角整理。

一句话回答

watch 需要你明确指定监听源,更适合精确控制;watchEffect 会自动收集回调里用到的响应式依赖,更适合快速声明一段副作用。

最稳的回答主线

  • watch:监听源明确,可拿新旧值
  • watchEffect:自动收集依赖,默认先执行一次
  • 两者都适合副作用,不适合替代 computed

最短记忆方式

watch 是我指定依赖,watchEffect 是你帮我找依赖。

创建于 2026/3/19 更新于 2026/5/27