在 Vue Options API 中,正确注销事件监听需用同一函数引用、在 beforeDestroy 钩子中移除,且绑定与解绑的 options 必须完全一致;匿名函数无法解绑,须用 data 中保存的具名 handler 和复用 options 对象,并统一清理定时器及第三方实例。

在 Vue Options API 中,正确注销事件监听的关键是:**用同一函数引用、在 beforeDestroy 钩子中移除、且绑定与解绑的 options 必须完全一致**。销毁钩子不是“补救时机”,而是唯一能确保 this 可靠、DOM 尚未移除、资源仍可安全释放的窗口。
必须用具名或变量保存的 handler 函数
匿名函数或箭头函数每次都是新引用,removeEventListener 无法匹配:
- ❌ 错误:
mounted() { window.addEventListener('resize', () => this.handleResize()) }→ 后续无法解绑 - ✅ 正确:
data() { return { resizeHandler: null } },然后在mounted中赋值:this.resizeHandler = () => { /* ... */ }; window.addEventListener('resize', this.resizeHandler) - 解绑时传入同一个
this.resizeHandler,就能精准清除
带选项的监听必须复用 options 对象实例
如果绑定时用了 { capture: true } 或 { passive: false },解绑时不能“重写一个看起来一样的对象”:
- ❌ 错误:
window.addEventListener('scroll', h, { capture: true }); window.removeEventListener('scroll', h, { capture: true })→ 新建对象,不匹配 - ✅ 正确:
data() { return { scrollOpts: { capture: true } } },绑定和解绑都用this.scrollOpts
全局监听器必须在 beforeDestroy 中统一清理
beforeDestroy 是 Options API 最稳妥的清理时机(destroyed 已太晚,this 可能失活):
- 所有
window、document、滚动容器上的监听,都要在这里调用removeEventListener - Vue 自定义事件也要配对解绑:
this.$off('custom-event', this.handler) - 建议把所有需清理的引用集中存到 data,例如:
unwatchList: [], eventHandlers: [],便于遍历清理
定时器和第三方库实例一并处理
事件监听只是泄漏源头之一,常与定时器、图表、地图等共存:
- 定时器 ID 存
data,用clearInterval(this.timerId)清理 - ECharts 实例调
this.chart.dispose(),Mapbox 调this.map.remove(),Swiper 调this.swiper.destroy(true) - 避免在
mounted中反复创建却只清一次,导致旧 ID 丢失、新监听残留


















