Sve*_*ort 8 javascript memory-leaks memory-management vue.js vuex
在 Vue 应用程序中,我遇到内存泄漏,发生的情况如下:
然而,分配的内存永远不会被释放,应用程序一开始的 RAM 使用量约为 30-40 MB,当渲染 v-for 时,RAM 使用量会增加到 200MB(最终会增加到超过 1GB,当更多元素时,浏览器会崩溃)添加或切换时)。当元素被删除时,它稳定地保持在 200MB(即使在手动垃圾收集时),所以它看起来像是保留了我的组件。
我尝试使用堆快照来定位问题,但它只显示一个子组件作为保留器。我无法找到导致该组件不被垃圾收集的原因。我已尝试取消订阅根上的所有事件侦听器,this.$root.off但这似乎根本没有帮助......
代码本身是保密的,所以我不能只是分享它,但是如果需要一些代码来理解问题,请告诉我,以便我可以提供一个复制的示例。
有谁知道如何解决这个问题,或者有任何想法如何找到内存泄漏的原因?
更新
这是在 v-for 中渲染组件的组件:
<template>
<b-tabs card class="tabMenu" v-model="index">
<b-tab v-for="(tab) in tabs" @click="doSomething" @change="doSomething">
<TabComponent :tab="tab"></TabComponent>
</b-tab>
</b-tabs>
</template>
<script>
import TabComponent from "./TabComponent";
export default {
components: {
TabComponent,
},
created: function () {
this.$root.$on("addTab", this.addTab);
},
data: function () {
return {
tabs: this.$store.state.tabs,
}
},
beforeDestroy: function(){
this.$root.$off("addTab");
},
methods: {
addTab(tab) {
this.$store.commit("addTab", {tab: tab});
},
}
};
</script>
Run Code Online (Sandbox Code Playgroud)
以及它呈现的选项卡组件:
<template>
<div @mousedown.stop>
<!-- Other components are loaded here but not relevant -->
<div>
<div v-show="conditionA">
<resize-observer @notify="doSomething" v-if="conditionC"></resize-observer>
<!-- This component renders many SVG elements which can be found in the heapsnapshot as DetachedSvgElements when the parent is not present anymore -->
<VisualizationComponent v-show="conditionD"
:tab="tab"></VisualizationComponent>
</div>
</div>
</div>
</template>
<script>
export default {
components: {
},
props: {
tab: TabObject,
},
data: function () {
return {
}
},
watch: {
// Some watchers
},
mounted: function () {
this.$nextTick(function () {
// Do some calculations
this.$root.$emit("updateSomething");
});
},
created: function(){
this.$root.$on("listen", this.doSomething);
// And listen to more events
},
beforeDestroy: function(){
this.$root.$off("listen");
// And unsubscribe all others
},
computed: {
// Quite a lot of computed props
},
methods: {
// And also many methods for data processing
}
}
</script>
Run Code Online (Sandbox Code Playgroud)
小智 7
我有类似的问题。在我的例子中,我通过属性传递给下一个组件的对象既复杂又大,我不知道你是否也是这种情况?
通过改变传递对象的方式解决了我的问题。通过将属性更改为数字(在本例中为 ID),我能够在使用该属性的组件中检索我的对象(基于 ID)。因此,我不必重复传递整个对象。由于某种原因,将大对象作为数据道具传递并不能正常工作,并会导致奇怪的行为......
在您的情况下,当您不将“tab”属性直接传递给组件,而是传递该元素在存储中的位置索引,然后直接从组件内的存储中获取它时,这可能会有所帮助。
所以你需要将你的 v-for 更改为:
<b-tab v-for="(tab, index) in tabs" @click="doSomething" @change="doSomething">
<keep-alive>
<TabComponent :tabIndex="index"></TabComponent>
</keep-alive>
</b-tab>
Run Code Online (Sandbox Code Playgroud)
在你的 TabComponent 中:
props: {
tabIndex: Number,
},
data: function () {
return {
tab: this.$store.state.tabs[this.tabIndex]
}
}
Run Code Online (Sandbox Code Playgroud)
当然,这一原则也需要应用于执行相同操作的任何子组件,以防止子组件中出现任何内存泄漏,这显然也会影响父组件。希望我能帮助你:)