单页应用中内存泄漏主因是组件卸载时资源未释放,须确保框架卸载钩子(如react useeffect清理函数、vue onunmounted、angular ngondestroy)被触发,并清除定时器、事件监听、websocket、第三方实例等引用,避免全局持有和闭包导致的强引用。

在单页应用(SPA)中,页面切换时组件未及时销毁是内存泄漏的常见原因。关键不是“手动销毁”,而是确保框架的生命周期机制正常触发,并避免人为持有对组件实例、DOM 节点、定时器、事件监听器或全局引用的强引用。
确保组件卸载钩子被正确调用
React、Vue、Angular 等主流框架都提供了组件卸载/销毁阶段的钩子(如 React 的 useEffect 清理函数、Vue 的 onUnmounted、Angular 的 ngOnDestroy)。这些钩子是释放资源的**唯一可靠入口**。
- React:在
useEffect中返回清理函数,用于清除定时器、取消请求、移除事件监听器 - Vue:在
onUnmounted中执行清理逻辑;组合式 API 中避免在setup外部保留响应式引用或副作用闭包 - Angular:在
ngOnDestroy中显式调用Subscription.unsubscribe()或destroy$等销毁信号
切断外部引用与全局监听
组件即使卸载,若仍被其他对象持有(如全局 Map、缓存对象、第三方库实例),JS 引擎无法回收其内存。
- 避免将组件实例、ref 或状态对象存入全局变量或静态属性
- 使用事件总线或自定义事件时,确保在卸载时调用
off或removeEventListener - 第三方图表/编辑器(如 ECharts、Monaco Editor)需主动调用其
dispose()方法 - WebSocket、EventSource 连接必须在卸载时
.close()并置空引用
警惕闭包与异步回调中的 this / state 持有
异步操作(如 fetch、setTimeout、Promise 回调)若在组件卸载后才执行,且回调中访问了已销毁组件的 state 或 DOM,不仅报错,还可能阻止垃圾回收。
- React:用
useRef标记组件是否已挂载,回调中先判断mounted.current === false则直接返回 - Vue:组合式 API 中可使用
onBeforeUnmount配合标志位,或使用asyncComputed类库内置取消能力 - 通用做法:为请求添加 AbortSignal,fetch 时传入
signal: abortController.signal,卸载时调用abortController.abort()
检查路由与组件复用行为
某些路由配置(如 Vue Router 的 keep-alive、React Router 的 element 缓存)会让组件不销毁而仅激活/停用。此时组件不会触发卸载钩子,但会触发激活钩子(如 activated / deactivated)。
- 确认是否真的需要
<keepalive></keepalive>;不需要时显式关闭,避免无意识缓存 - 若启用缓存,应在
deactivated中暂停定时器、断开连接,在activated中恢复,而非依赖unmounted - 动态 import 的路由组件应确保模块本身不产生全局副作用(如污染 window、注册全局监听)
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











