Vue组件销毁时内存泄漏主因是未手动清理外部资源:需在unmounted中清除定时器、abort请求、解绑事件监听器、销毁第三方实例、停止watch并避免强引用响应式对象。

Vue组件销毁时内存泄漏,核心在于你手动引入的外部资源没被清理——Vue不会替你解绑全局事件、清除定时器、中断请求或销毁第三方实例。unmounted钩子不是自动回收开关,而是你主动释放资源的明确时机。
清理定时器和未完成的异步操作
在setup中用setTimeout、setInterval或发起fetch/axios请求后,若组件已卸载,回调仍可能执行并尝试修改响应式数据,导致警告甚至内存泄漏。
- 用ref保存定时器ID,在unmounted中调用clearTimeout或clearInterval
- 对fetch请求,创建AbortController实例,传入signal选项;在unmounted中调用controller.abort()
- 避免在then/catch里直接赋值ref,不依赖isMounted标记,优先用abort机制切断链路
解绑所有手动添加的事件监听器
通过window、document、EventBus或mitt绑定的监听器,不会随组件自动移除,必须成对清理。
Vue 3 组合式 API 与 最佳实践,涵盖代码组织、useXxx 模式、组合式函数设计、Store 集成、响应式优化及功能抽取。
- window.addEventListener('resize', handler) → unmounted中window.removeEventListener('resize', handler)
- 使用mitt时,保存emitter.on()返回的off函数,并在unmounted中执行它
- 封装成useEventListener等组合式函数,让绑定与解绑逻辑天然耦合
销毁第三方库实例
地图、图表、编辑器等库通常有独立生命周期,不遵循Vue规则,必须显式调用销毁方法。
立即学习“前端免费学习笔记(深入)”;
- ECharts:chart.dispose()
- Monaco Editor:editor.dispose()
- Leaflet:map.remove()
- Vue.Draggable(基于SortableJS):sortable.destroy(),并重置draggingElement等全局引用
停止watch和释放大型响应式引用
watch、watchEffect返回的停止函数需手动调用;同时避免将响应式对象挂到window或长期持有大数组/对象强引用。
- const stop = watch(...); unmounted中调用stop()
- 不要写window.myData = reactive({...}),防止意外延长生命周期
- 缓存大量数据时,设为null或改用WeakMap管理,减少垃圾回收障碍

















