onCleanup 是 Vue 传入 watchEffect 回调的参数,用于注册清理函数,在下次执行前或组件卸载时自动取消过期异步操作;常见用途包括 abort fetch、clearTimeout、移除事件监听等,需配合 AbortController 解决竞态问题。

onCleanup 不是手动“写”的函数,而是 Vue 传入的参数,你只需在回调中调用它,并传入一个清理逻辑函数。它的核心作用是在副作用重新执行前或组件卸载时,自动帮你取消过期的异步操作,从而解决竞态问题。
onCleanup 的基本写法
它只接收一个函数作为参数,这个函数会在下次 watchEffect 执行前或组件销毁时被调用:
- 在 watchEffect 回调中,第三个参数位置(实际是第一个参数的形参)就是 onCleanup
- 不能自己定义 onCleanup,也不能提前调用它——必须等 Vue 在合适时机触发
- 清理函数里通常做:abort fetch 请求、clearTimeout / clearInterval、取消 Promise 订阅等
处理异步请求竞态(最常见场景)
用户快速输入搜索词,多个请求并发发出,但只有最后一个应生效。靠 onCleanup + AbortController 实现自动取消:
- 每次进入 watchEffect 都新建一个 AbortController
- 把 controller.signal 传给 fetch
- 立即用 onCleanup 注册 controller.abort()
- 请求返回后,检查是否已被取消(比如用布尔标记或 signal.aborted),再更新状态
清理定时器和事件监听器
除了网络请求,onCleanup 同样适用于其他长期运行的副作用:
- 启动 setInterval 后,在 onCleanup 中调用 clearInterval
- 添加全局事件监听(如 window.resize)后,在 onCleanup 中 removeEventListener
- 创建第三方库实例(如 Mapbox 地图)后,在 onCleanup 中调用其 destroy 方法
注意执行时机和停止侦听器
onCleanup 的回调默认在下一次副作用执行前触发,不是在组件 unmounted 时才执行。如果需要彻底停掉 watchEffect,应显式调用其返回的 stop 函数:
- const stop = watchEffect(() => { ... })
- 后续可调用 stop() 主动终止侦听
- 组件卸载时 Vue 会自动调用 stop,同时触发已注册的 onCleanup

















