Vue组件销毁后内存没释放,是不是哪里引用没清理?
我在一个 Vue 项目里做单页应用,切换路由时发现内存占用一直在涨。用 Chrome 的 Performance 面板看了下,卸载的组件好像没被 GC 回收。我明明在 beforeUnmount 里清了定时器和事件监听,但还是有内存泄漏。
比如下面这个组件,我绑了个 resize 监听,也手动移除了,但 heap snapshot 里还能看到它:
export default {
mounted() {
this.handleResize = () => { /* ... */ };
window.addEventListener('resize', this.handleResize);
},
beforeUnmount() {
window.removeEventListener('resize', this.handleResize);
}
}
是不是还有其他地方会隐式持有引用?比如闭包、全局变量或者第三方库的问题?
常见的问题点:
1. 闭包陷阱 — 你的 handleResize 如果用了 this,或者在回调里访问了组件的数据,那这个函数本身就形成了一个闭包,把整个组件实例给锁住了。window.addEventListener 第二个参数是函数引用,你移是移了,但如果这个函数本身闭包了组件,一样没用。
2. 定时器漏了 — setInterval 和 setTimeout 这类东西很容易忘,检查下代码里有没有没 clear 掉的。
3. 第三方库没销毁 — 比如你用了 echarts、swiper、videojs 之类的东西,得手动调它们的 dispose 方法,光销毁 Vue 组件没用。
4. Vue Router 的钩子 — 如果你在路由守卫里用了 this 或者存了组件引用,得确保守卫里没拖泥带水。
5. bus 或 mitt — 如果用事件总线订阅了事件,beforeUnmount 里一定要 unsubscribe。
给你个排查思路:打开 DevTools 的 Memory 面板,用 heap snapshot 对比一下,搜索你的组件名或者变量名,看看到底是谁在引用它。Chrome 的 Retainers 面板能直接看到引用链,一层层点开找根源。
如果怀疑是闭包问题,可以改成箭头函数或者把组件数据先存到普通变量里再用,别直接 this.xxx 硬刚。