watcheffect 的依赖集合是每次执行时实际访问的响应式值的快照,分支切换导致某些值未被读取,因而下轮不追踪,并非主动清理;oncleanup 仅处理副作用生命周期,不影响依赖收集。

watchEffect 在条件分支改变时“自动清理旧依赖”,并不是它主动删掉某个已收集的依赖,而是它根本不会继续追踪那些没被再次执行到的分支里的响应式数据。它的依赖集合始终是“本次函数执行过程中实际访问过的响应式值”的快照。分支切换只是让某些值在本轮不被读取,下一轮自然就不在依赖列表里了——没有“清理”动作,只有“不收集”。
依赖只来自当前执行路径
watchEffect 每次运行,都像重新做一次“现场扫描”:只记录这次代码真正走过的路径中读取的响应式变量。如果某次执行进了 if (show.value) { name.value },那依赖只有 show 和 name;下次 show.value 变成 false,函数仍会执行,但只读了 show.value,name.value 没被访问,就不会再监听它。
- 不是“移除 name 的监听”,而是“这次根本没碰 name”
- 依赖列表每次都是全新生成,不是在旧列表上增删
- 所以看似“清理”,实则是“不重拾”
典型场景:搜索状态切换
比如一个搜索组件,有关键词和分页两个 ref:
const query = ref('')<br>const page = ref(1)<br>watchEffect(() => {<br> if (query.value) {<br> fetchData(query.value, page.value) // 用到 query 和 page<br> } else {<br> clearResults()<br> }<br>})
当 query 从非空变为空时:
- 函数重新执行,但只读
query.value(进 else 分支) -
page.value没被访问,不再成为依赖 - 此后改
page值,watchEffect 不会再触发
注意:清理函数 onCleanup 不负责这个
onCleanup 是用来处理副作用本身的生命周期(如取消定时器、abort 请求),和依赖追踪无关。它在下一次 watchEffect 执行前调用,但不影响哪些值被追踪——那完全由函数体内的读取行为决定。
所谓“分支切换导致依赖变化”,本质是代码执行流变了,Vue 的响应式系统顺势更新了依赖图。不需要干预,也不可配置,它是机制使然。











