Вю утечки памяти при отображении компоненты удаляются
В приложении Vue я сталкиваюсь с утечкой памяти, сценарий, в котором это происходит, выглядит следующим образом:
- У нас есть компонент, который отображается в пределах v-для которого содержится много дочерних компонентов
- Когда соответствующий элемент удаляется из массива, v-for повторно передает эти компоненты и правильно удаляет компонент, соответствующий элементу, удаленному из массива.
Однако выделенная память никогда не освобождается, приложение запускается с использованием ~30-40 МБ оперативной памяти, которая увеличивается до 200 МБ оперативной памяти при визуализации v-for (и в конечном итоге доходит до более чем 1 ГБ и завершает работу браузера при добавлении большего количества элементов или при переключении). Когда элемент удаляется, он стабильно остается на уровне 200 мб (даже при ручном сборе мусора), поэтому кажется, что он сохраняет мой компонент.
Я попытался найти проблему с моментальными снимками кучи, но она показывает только дочерний компонент в качестве фиксатора. Я не могу найти то, что заставляет этот компонент не быть собранным мусором. Я попытался отписаться от всех слушателей событий в корневом каталоге с 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>
И компонент tab, который он отображает:
<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>














Ответы - Вю утечки памяти при отображении компоненты удаляются / Vue memory leak when rendered components are removed

05.01.2020 03:35:11
Вы приказываете vue сохранить ваши компоненты живыми и спрашиваете, почему они живы?!!!
Решение:
Просто добавив max
проп <keep-alive>
судо-компонент и передавая tabs.length
значение длины заставит его отказаться от удаленных единиц.
<keep-alive :max="tabs.length">
...
</keep-alive>
Смотри хранить документы



06.01.2020 03:19:49
У меня была похожая проблема. Объект, который я передал через свойство следующему компоненту, был сложным и большим в моем случае, я не знаю, так ли это и для вас?
Моя проблема была решена путем изменения способа прохождения моего объекта. Изменив свойство на число, в моем случае идентификатор, я смог получить свой объект в компоненте, где используется свойство (на основе идентификатора). В результате мне не пришлось проходить по всему объекту повторно. По какой-то причине передача больших объектов в качестве реквизитов данных не работает должным образом и вызывает странное поведение...
В вашем случае это может помочь, если вы не передаете свойство " 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>
И в вашем Табкомпоненте:
props: {
tabIndex: Number,
},
data: function () {
return {
tab: this.$store.state.tabs[this.tabIndex]
}
}
Конечно, этот принцип также должен быть применен к любым дочерним компонентам, делающим то же самое, чтобы предотвратить любые утечки памяти в дочерних компонентах, которые, очевидно, также повлияют на родителей. Надеюсь я смогу вам помочь :)