清理工作应在 onBeforeUnmount 中执行,因其在组件卸载前触发,可安全访问实例、DOM 和响应式数据;onUnmounted 仅适合日志记录等收尾操作。

销毁阶段的清理工作,关键在 onBeforeUnmount,而不是等 onUnmounted 才动手。
onBeforeUnmount 是清理副作用的主战场
这个钩子在组件从 DOM 移除前触发,此时组件实例依然完整、响应式数据可读、DOM 元素仍存在、事件监听和定时器都还活跃——这正是执行清理操作的理想窗口。
- 清除定时器:
clearInterval或clearTimeout必须在此处调用,否则计时器持续运行,造成内存泄漏 - 移除全局事件监听:
window.removeEventListener、document.removeEventListener需在此解绑,避免触发已销毁组件的方法 - 关闭 WebSocket 连接:
socket.close()应在此执行,防止连接残留和重复重连 - 取消未完成的请求:若使用 AbortController,需调用
controller.abort()终止 pending 请求
onUnmounted 更适合收尾与验证
该钩子在组件完全卸载、实例被 Vue 销毁后调用。此时 this 不再可用(组合式 API 中无 this),DOM 已脱离文档,响应式状态也已释放。它不适合做资源清理,但可用于:
- 日志记录:如
console.log('组件已彻底卸载'),便于调试生命周期流程 - 轻量级状态归零:仅限写入外部可观察状态(如全局统计对象),不依赖组件内部数据
- 配合测试断言:在单元测试中确认组件是否按预期销毁
常见误用与风险提示
把清理逻辑放在 onUnmounted 里,看似“更彻底”,实则危险:
立即学习“前端免费学习笔记(深入)”;
- DOM 元素已不存在,尝试访问
document.getElementById会返回 null,可能引发报错 - 响应式引用(ref)已被回收,读取其 .value 可能报错或返回 undefined
- 第三方库实例(如 ECharts、Map 实例)若未在 onBeforeUnmount 中销毁,可能继续占用内存并触发渲染异常
- 在 KeepAlive 场景下,onUnmounted 不一定触发(组件被缓存而非销毁),导致清理逻辑永远不执行
推荐写法示例
保持逻辑清晰、职责分明:
import { onBeforeUnmount, onUnmounted } from 'vue'
let timer = null
let resizeHandler = () => {}
onBeforeUnmount(() => {
if (timer) clearInterval(timer)
window.removeEventListener('resize', resizeHandler)
// 若有 ECharts 实例,调用 myChart.dispose()
})
onUnmounted(() => {
console.debug('✅ 组件实例已释放')
})


















