WeakMap在Vue组件里怎么用才不会内存泄漏?
我在Vue组件里想用WeakMap缓存一些DOM节点的元数据,但不确定会不会导致内存泄漏。试了下发现组件卸载后WeakMap里的引用好像还在?
这是我的写法:
<template>
<div ref="container"></div>
</template>
<script>
export default {
mounted() {
const meta = new WeakMap();
meta.set(this.$refs.container, { id: 'panel-1', visible: true });
// 存到组件实例上方便后续访问
this._metaCache = meta;
},
beforeUnmount() {
// 这里需要手动清理吗?
}
}
</script>
WeakMap不是自动清理的吗?为什么我担心卸载后还占着内存?
WeakMap 确实会在键对象被垃圾回收时自动清理对应条目,但前提是 WeakMap 本身没有被强引用持有。你现在把 WeakMap 挂在
this._metaCache上,组件实例本身就是一个强引用。只要组件实例还活着,WeakMap 就一直在内存里。Vue 组件卸载时,如果组件实例没有被正确回收(这取决于 Vue 的实现和是否有其他引用指向这个实例),那这个 WeakMap 就会一直占着内存。简单说:WeakMap 只能保证"键对象没了,对应的值跟着没",但保证不了"WeakMap 本身被回收"。
正确做法是在 beforeUnmount 里手动清掉:
其实吧,如果你只是想在组件内缓存 DOM 元数据,直接用普通 Map 或者干脆挂载在组件实例上都行,反正组件销毁时实例本身就被回收了。用 WeakMap 的意义在于你想在组件外部(比如模块级缓存)存储一堆 DOM 节点的元数据,又不想自己管理清理逻辑这时候 WeakMap 才真正发挥作用。
你这种场景下,WeakMap 反而增加了复杂度,没太大必要。
如果还是担心,可以这样写确保清除:
但实际没必要,就这样。