KeepAlive下应使用activated/deactivated替代mounted/unmounted管理全局事件:在activated中绑定,在deactivated中解绑;同时用onBeforeUnmount兜底清理,避免重复绑定和内存泄漏。

在 Vue 中使用 <keepalive></keepalive> 缓存组件时,组件的生命周期会变化:mounted 和 unmounted 不再按常规触发,而是由 activated / deactivated 替代。因此,若在 mounted 中绑定全局事件(如 window.resize、document.addEventListener 或自定义 bus / mitt 事件),而未在对应时机解绑,就会导致多次激活后重复绑定,回调被反复触发。
✅ 在 activated 中绑定,在 deactivated 中解绑
这是最直接、推荐的做法。利用 KeepAlive 组件特有的两个钩子,确保每次激活时绑定、失活时清理:
- activated:组件被激活(从缓存中唤醒)时执行,适合初始化监听器
- deactivated:组件被停用(进入缓存)时执行,必须在此处移除事件监听
示例(Vue 3 + Composition API):
import { onActivated, onDeactivated, onBeforeUnmount } from 'vue'
import mitt from 'mitt'
<p>const emitter = mitt()</p><p>onActivated(() => {
// 每次激活都绑定(但不会重复,因为上一次已在 deactivated 清理)
const handler = () => console.log('窗口大小改变')
window.addEventListener('resize', handler)</p><p>// 保存 handler 引用,便于后续移除
window.__resizeHandler = handler
})</p><p>onDeactivated(() => {
// 确保移除,避免残留
window.removeEventListener('resize', window.<strong>resizeHandler)
delete window.</strong>resizeHandler
})</p><p>// 补充:如果组件可能被销毁(非仅缓存),也建议在 onBeforeUnmount 清理兜底
onBeforeUnmount(() => {
if (window.<strong>resizeHandler) {
window.removeEventListener('resize', window.</strong>resizeHandler)
delete window.__resizeHandler
}
})
✅ 使用 setup() 中的 onBeforeUnmount 做兜底清理
即使组件被 KeepAlive 缓存,当整个路由或父组件卸载时,onBeforeUnmount 仍会执行。可将事件绑定逻辑封装 + 引用保存,统一在该钩子中解绑,更安全可靠:
- 把事件监听器声明为
ref或局部变量 - 在
onActivated中绑定(只在需要时) - 在
onBeforeUnmount中无条件解绑(覆盖所有销毁场景)
这样既适配 KeepAlive 场景,也兼容非缓存路径,避免遗漏。
✅ 避免在 created/mounted 中绑定全局事件
KeepAlive 下,created 和 mounted 只执行一次(首次进入),但组件可能被反复 activated;若监听器依赖组件内部状态(如 ref、props),而状态已更新,旧监听器却仍引用过期闭包,会导致逻辑异常或内存泄漏。
- ❌ 错误做法:在
mounted绑定 resize,并假设它“一直有效” - ✅ 正确做法:在
activated中重新绑定,确保闭包捕获最新响应式数据
✅ 使用事件总线时,优先用 mitt 的 removeListener 或 off
若用 mitt / EventBus,不要只靠组件销毁自动清理。需显式调用 emitter.off() 或保存 listener 引用后精准移除:
let handler
<p>onActivated(() => {
handler = (data) => { /<em> 处理逻辑 </em>/ }
emitter.on('user-login', handler)
})</p><p>onDeactivated(() => {
if (handler) {
emitter.off('user-login', handler)
}
})
不推荐用匿名函数绑定,否则无法精确解绑。

















