核心是卸载前清除定时器并避免闭包持有组件引用:在 mounted/onMounted 启动并存 ID,在 beforeUnmount/onBeforeUnmount 清理,启动前先清旧定时器,回调中减少响应式数据访问,必要时用 RAF 替代 setInterval。

核心解决思路是:在组件卸载前主动清除定时器,同时避免闭包长期持有对组件实例或大型数据的引用。
在生命周期钩子中配对使用
这是最基础也最关键的防护手段。必须确保 setInterval 和 clearInterval 成对出现,且清理时机明确。
- 在 mounted 或 onMounted 中启动定时器,并将返回的 ID 存入响应式数据(如
data或ref) - 在 beforeUnmount(Vue 3 Composition API 推荐)或 beforeDestroy(Vue 2)中调用
clearInterval - 增加空值判断,防止重复清理或清理未定义 ID:
if (this.timer) clearInterval(this.timer)
防止定时器叠加运行
组件可能因路由复用、v-if 切换或错误重试而被反复挂载。若未清旧启新,多个定时器会同时执行。
- 每次启动前先清理已有定时器:
clearInterval(this.timer); this.timer = setInterval(...) - 在 setup 中使用
onBeforeUnmount清理,比依赖data更可靠 - 避免在异步回调(如
await fetchData()后)再次启动定时器,除非确认组件仍存活
切断闭包对组件状态的隐式引用
定时器回调函数若访问 this.xxx、ref.value 或大型对象,会阻止 GC 回收整个组件实例。
- 回调中只做必要操作,避免直接读写响应式数据;可改用事件总线或 provide/inject 通信
- 对大对象(如图表数据、日志列表)不直接闭包引用,改用 ID 或轻量标识符
- 必要时在清理定时器后,手动将相关 ref 设为
null,辅助垃圾回收
用 requestAnimationFrame 替代低频轮询
对于 UI 更新类任务(如动画、倒计时),requestAnimationFrame 比 setInterval 更高效且自动暂停。
- 它随浏览器刷新节奏执行,不会在页面不可见时浪费资源
- 无需手动清理:标签页切走时,RAF 自动暂停;切回后继续,无内存堆积
- 可用封装函数模拟 setInterval 行为,但底层基于 RAF,更安全

















