Vue 3 中事件绑定未及时移除会导致内存泄漏,因手动添加的监听器需手动清除;必须使用同一函数引用、在 unmounted 中成对解绑,推荐 useEventListener 等自动清理方案。

Vue 3 中事件绑定未及时移除引发内存泄漏,核心在于:你手动加的监听器,Vue 不会自动帮你删。只要回调函数还被全局对象(比如 window、document 或自定义事件总线)持有,组件实例就无法被垃圾回收。
确保监听函数可精确移除
匿名函数和箭头函数无法被 removeEventListener 正确识别,必须使用同一引用的具名函数或方法。
- ✅ 正确写法:在
setup中定义并复用同一个函数 - ❌ 错误写法:
window.addEventListener('resize', () => {...})+window.removeEventListener('resize', () => {...})—— 两个箭头函数是不同引用,移除失败 - ⚠️ 注意
this绑定:若用methods中的方法,避免用handleResize.bind(this),它每次返回新函数;改用handleResize原函数引用
在 unmounted 钩子中成对清理
unmounted 是唯一可靠、语义明确的清理时机,所有手动添加的监听都必须在这里解绑。
从零开始编排 SpringBoot+Vue 全栈项目工作流,适用于新建全栈项目或完整脚手架请求,触发后依次调用 product‑spec‑builder(需求调研)等模块。
-
window.addEventListener('resize', handler)→unmounted中调用window.removeEventListener('resize', handler) - 用
mitt或EventBus时,保存emitter.on()返回的off函数,并在unmounted中执行它 - 对
document、body或第三方容器(如地图 DOM 节点)绑定的监听,同样需一一对应清除
优先使用封装好的组合式函数
自己手写绑定+解绑容易遗漏,推荐用 @vueuse/core 的 useEventListener,它自动在组件卸载时解绑。
立即学习“前端免费学习笔记(深入)”;
- 示例:
useEventListener(window, 'resize', handler)—— 无需手动管理生命周期 - 也可封装自己的
useGlobalListener,内部用onUnmounted注册清理逻辑,让绑定与解绑天然耦合 - 对 resize 等高频事件,建议结合防抖(如
lodash-es/debounce)再监听,减少闭包压力
警惕事件总线与 WebSocket 的隐式引用
全局事件总线或 WebSocket 实例若采用“随意注册、无人注销”模式,极易形成监听器堆积。
- 避免把回调直接 push 到全局数组里;改用带唯一 ID 或 token 的注册机制,支持按 ID 清理
- WebSocket 场景下,组件内
onmessage回调应绑定到当前实例作用域,并在unmounted中显式调用removeListener或关闭通道 - 更稳健做法:用
provide/inject或 Pinia store 管理通信,配合onActivated/onDeactivated控制监听启停

















