Подтвердить что ты не робот

Невозможно очистить отдельные элементы DOM

Я использую jquery-ui вкладки, и у меня возникла проблема, возникающая при удалении вкладки. Вкладка, как представляется, будет удалена вместе с ее содержимым div, но когда вы посмотрите на кучу в профилях Chrome DevTools (после того, как вкладка была удалена), вы увидите, что элементы tab и div все еще присутствуют, но отсоединены, Со временем повторное добавление/удаление вкладок заставляет эти элементы накапливаться. Например, если вы добавите вкладку 10 раз, в снимке кучи появится 10 отдельных элементов div и 10 отдельных элементов li:

Heap snapshot with detached elements

У меня есть следующие представления:

TabLabel = Marionette.ItemView.extend({
    template: "#tab-label",
    tagName: "li",
    events: {
        "click .ui-icon-close": "closeTab"
    },  
    closeTab: function(e) {
        this.$el.contents().remove();
        this.model.collection.remove(this.model);
        $("#main-container").tabs("refresh");
        this.close();
    }   
}); 

TabContainer = Marionette.ItemView.extend({
    template: "#tab-container",
    tagName: "div",
    onBeforeRender: function() {
        this.$el.attr("id", "div-" + this.id);
    },  
    onClose: function() {
        // This removes the region that contains the container
        App.layout.removeRegion(this.containerRegion);
    }   
});

TabLabels = Marionette.CollectionView.extend({
    tagName: "ul"
});

TabContainers = Marionette.CollectionView.extend({
    tagName: "div"
});

Представления создаются так:

tabs = new TabsCollection(); // Create a new collection instance

var tabLabelView = new TabLabels({
    itemView: TabLabel,
    collection: tabs
}); 

var tabContainerView = new TabContainers({
    itemView: TabContainer,
    collection: tabs
}); 

Как вы можете видеть, представления относятся к одной коллекции; каждая модель в коллекции может быть представлена ​​как одна вкладка (так бывает, что модель содержит необходимую информацию для удовлетворения вкладок jquery-ui). Представления отображаются в регионе через Marionette.Layout... довольно стандартный. Добавление вкладки осуществляется путем нажатия ссылки в контейнере табуляции; все это добавляет еще одну модель в коллекцию, а затем вызывает вкладки ( "обновление" ) в основном контейнере, что делает новую вкладку. Удаление вкладки выполняется щелчком по значку "X" в верхнем правом углу вкладки.

Я потратил много времени, пытаясь отследить эту утечку, и я не могу понять, является ли это проблемой в моем коде (как я могу закрывать представления/модели/и т.д., возможно?), или если это проблема в плагине вкладок jquery-ui.

Мысли? Спасибо заранее!

Обновление # 1 В соответствии с запросом, здесь jsfiddle демонстрирует проблему - просто закройте вкладки и вы увидите, что отдельные элементы остались позади.

Также снимок экрана:

enter image description here

Обновление # 2 Это похоже на утечку в виджетах jquery-ui tabs. Такое же поведение наблюдается в демонстрации виджета на веб-сайте jquery-ui. Я добавил несколько вкладок, а затем закрыл их и, конечно же, продолжал:

enter image description here

Я тестировал это с помощью последней версии (на момент написания этой статьи) версии jQuery UI (1.10.3) и предыдущей версии (1.10.2).

4b9b3361

Ответ 1

Поэтому я в конце концов исправил эту проблему (довольно давно), выполнив две вещи:

  • Отключение jQueryUI в пользу Bootstrap
  • Изменение функции closeTab (см. исходный jsFiddle) на следующее:

    closeTab: function (e) {
        e.stopPropagation();
        e.preventDefault();
        this.model.collection.remove(this.model);
        this.close();
    }
    

В этом фрагменте stopPropagation и preventDefault действительно то, что остановило этот элемент от оставшегося отсоединения (и накапливается при последующих добавлениях/удалениях) в DOM. Подводя итог: эта проблема была создана, не вызывая stopPropagation/preventDefault для объекта события после его запуска. Я обновил jsFiddle, чтобы он правильно удалял элементы вкладки и для потомков, вот скриншот результата:

Updated jsFiddle

Как вы можете видеть, ни один из элементов вкладки не отсоединяется после нажатия кнопки "X", чтобы закрыть их. Единственными отдельными элементами являются те, которые поступают из интерфейса jsFiddle.

Ответ 2

Есть ли причина, по которой вы используете this.$el.contents().remove() вместо this.$el.empty()?

Используя this.$el.empty() в том, что jsFiddle из вас, казалось, исправил отдельный NodeList.

Несколько профилей памяти примечаний:

  • смотреть http://www.youtube.com/watch?v=L3ugr9BJqIs
  • Использовать 3 метода моментальных снимков, 2 недостаточно. Что это значит?
    • Начать новый, инкогнито и обновить
    • Сделать снимок (принудительный GC будет выполняться каждый раз, когда вы делаете снимок)
    • Сделайте что-нибудь, сделайте снимок (gc)
    • Сделайте что-нибудь подобное, сделайте снимок (gc)
    • Сравнить моментальный снимок 2 с моментальным снимком 1, найти дельта с +
    • Выберите "Сводка" и "Объекты, выделенные между моментальными снимками 1 и 2 для моментального снимка 3"
    • Ищите вещи, которые вы нашли, сравнивая 2 и 1, которые не должны быть там. Это лук-порей

Я нашел случаи, когда jQuery кажется лук-порей, потому что они сохраняют текущий объект jQuery в .prevObject при выполнении некоторых операций, таких как вызов .add(). Может быть, этот призыв к .contents() делает какую-то фанки магии.