Вю утечки памяти при отображении компоненты удаляются

Вю утечки памяти при отображении компоненты удаляются

23.12.2019 02:52:31 Просмотров 45 Источник

В приложении 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>
У вопроса есть решение - Посмотреть?

https://stackoverflow.com/questions/59454894/vue-memory-leak-when-rendered-components-are-removed#comment105091182_59454894
Наверняка потребуется какой-то пример кода
https://stackoverflow.com/questions/59454894/vue-memory-leak-when-rendered-components-are-removed#comment105091680_59454894
Я бы предложил удалить дочерние компоненты по отдельности, чтобы увидеть, где находится проблема. Есть ли какие-либо из этих компонентов: 1) прямое манипулирование DOM? 2) Создание объектов в Vuex? 3) Работа с большими наборами данных?
https://stackoverflow.com/questions/59454894/vue-memory-leak-when-rendered-components-are-removed#comment105091929_59454894
@T. Short, добавил некоторый код, который напоминает мой фактический код, я надеюсь, что это делает его более ясным
https://stackoverflow.com/questions/59454894/vue-memory-leak-when-rendered-components-are-removed#comment105091987_59454894
@Dan, да, некоторые из этих компонентов хранят данные в Vuex, и наборы данных определенно большие, и на этих данных выполняется большая обработка, которая затем визуализируется в результате большого количества компонентов и узлов DOM (в диапазоне от нескольких тысяч до полумиллиона)
https://stackoverflow.com/questions/59454894/vue-memory-leak-when-rendered-components-are-removed#comment105092250_59454894
@HelderLucas, в самом коде b-tab действительно содержит ключ, забыл упомянуть об этом. Кроме того, когда мы удаляем компонент, мы удаляем его в Vuex, и это отражается обратно, так как вкладки напрямую связаны с состоянием. Так что я точно знаю, что его убрали из магазина... Это самое странное для меня....
https://stackoverflow.com/questions/59454894/vue-memory-leak-when-rendered-components-are-removed#comment105092676_59454894
Вы уверены, что правильно удаляете SVG-элементы из DOM? Сохраняется ли проблема, если удалить компонент визуализации?
https://stackoverflow.com/questions/59454894/vue-memory-leak-when-rendered-components-are-removed#comment105093294_59454894
@Dan, когда я комментирую все элементы SVG в компоненте визуализации, утечка все равно происходит (хотя это явно меньше утечки, так как в этот момент она почти ничего не отображает), а также когда я полностью отключаю компонент визуализации
https://stackoverflow.com/questions/59454894/vue-memory-leak-when-rendered-components-are-removed#comment105099071_59454894
Посмотрите на официальный пример утечки памяти Vue здесь и убедитесь, что ваше приложение нигде не создает эту проблему (в частности, глядя на SVGs, а также на любые другие манипуляции DOM). Вы заметите, что утечки памяти, как правило, являются результатом манипуляций DOM третьей стороны, которые не были должным образом очищены.
https://stackoverflow.com/questions/59454894/vue-memory-leak-when-rendered-components-are-removed#comment105117661_59454894
@Dan, спасибо за ваш ответ. Мы не используем никакие сторонние библиотеки для манипуляции DOM и даже исключение всех элементов svg не предотвращает утечку (к вашему сведению, мы используем vuetify/bootstrap vue, могут ли они вызвать проблему?)
https://stackoverflow.com/questions/59454894/vue-memory-leak-when-rendered-components-are-removed#comment105237399_59454894
@Dan, удаление keep alive, к сожалению, не имеет никакого значения....
https://stackoverflow.com/questions/59454894/vue-memory-leak-when-rendered-components-are-removed#comment105240629_59454894
Слишком плохо, это может помочь восстановить в новом проекте файл за файлом, пока вы не поймете это. (Пожалуйста, доложите, если вы когда-нибудь поймете это)

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

Ali

05.01.2020 03:35:11

Вы приказываете vue сохранить ваши компоненты живыми и спрашиваете, почему они живы?!!!

Решение: Просто добавив max проп <keep-alive> судо-компонент и передавая tabs.lengthзначение длины заставит его отказаться от удаленных единиц.

<keep-alive :max="tabs.length">
...
</keep-alive>

Смотри хранить документы

https://stackoverflow.com/questions/59454894/vue-memory-leak-when-rendered-components-are-removed/59596081#comment105361083_59596081
Спасибо за ваш ответ, однако, если вы посмотрите на комментарии, которые я попытался полностью удалить keep-alive, что не имеет никакого значения. ;)
https://stackoverflow.com/questions/59454894/vue-memory-leak-when-rendered-components-are-removed/59596081#comment105425087_59596081
вы пробовали атрибут' max'?
Является ответом!
Kimberley

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]
    }
}

Конечно, этот принцип также должен быть применен к любым дочерним компонентам, делающим то же самое, чтобы предотвратить любые утечки памяти в дочерних компонентах, которые, очевидно, также повлияют на родителей. Надеюсь я смогу вам помочь :)

Закрыть X