Нужно ли удалять события из DOM, если элемент удален? - PullRequest
3 голосов
/ 30 сентября 2011

Допустим, у меня есть страница, которая загружает страницы динамически.Когда каждая страница загружается в DOM, события для элементов на этой странице добавляются.

Если пользователь загружает другую страницу, ранее загруженные элементы будут удалены из DOM.Естественно, поскольку сами элементы больше не существуют, любые события, сопоставленные с этими элементами, перестают функционировать.

Однако они также удаляются?Или они сидят в памяти пользователя, занимая место?

Последующие действия: Была ли функция определена так:

var event = $('foobar').addEvent('click', function() {
    alert(1);
});

Можно легко удалить событие с помощью event = null (или так я бы предположил!) ...

но что, если событие не было сохранено в локальной переменной?

$('foobar').addEvent('click', function() {
    alert(1);
});

Спасибо!

Ответы [ 3 ]

1 голос
/ 01 октября 2011

Я обнаружил, что в старых версиях IE, похоже, есть проблемы с добавлением и удалением большого количества элементов с привязанными к ним событиями. Основная причина - циклические ссылки, которые нельзя собрать мусором. Вы можете найти больше информации здесь: http://msdn.microsoft.com/en-us/library/Bb250448

Установка на ноль не удалит событие, а просто удалит ссылку на событие. Вам нужно использовать как element.removeEventListener, так и element.detachEvent (в зависимости от браузера), или если вы используете jquery, unbind должен работать.

Кроме того, есть инструменты для обнаружения утечек, этот работает хорошо (по словам коллеги): http://blogs.msdn.com/b/gpde/archive/2009/08/03/javascript-memory-leak-detector-v2.aspx

1 голос
/ 03 октября 2011

в первую очередь.что?это не имеет смысла:

var event = $('foobar').addEvent('click', function() {
    alert(1);
});

это не сохраняет событие в локальную переменную, как вы, кажется, думаете.он сохраняет ссылку на foobar element object в переменную event - большинство методов элемента mootools возвращают this для объединения в цепочку, которое является самим элементом, а не результатом метода (если это не метод получения, подобный '.getStyle').

это зависит от того, как вы избавитесь от элемента, что произойдет дальше.во-первых, element.destroy, найденный здесь: https://github.com/mootools/mootools-core/blob/master/Source/Element/Element.js#L728

он удалит элемент из памяти и из памяти и очистит его безопасным способом.после очистки он будет зависеть от GC браузера, mootools не сделает для вас никакого впечатляющего GC для самого элемента, но он также выполняет специальную функцию clean на дочерних узлах: var children = clean(this).getElementsByTagName('*');.

метод clean также избавляет от любых обработчиков событий и хранилищ, прикрепленных к дочерним элементам div.

ТО.события, добавленные mootools, попадают в хранилище элементов.Хранение элемента находится в объекте за замыканием, которое использует элемент proto.Чтобы протестировать его, мы повторно реализуем его и сделаем его пунктируемым (глобальный объект, называемый хранилищем), чтобы мы могли проверить, что происходит со ссылкой после того, как родительский элемент пропал:

http://jsfiddle.net/dimitar/DQ8JU/

(function() {
    var storage = this.storage = {}; // make it puncturable

    var get = function(uid){
        return (storage[uid] || (storage[uid] = {}));
    };

    Element.implement({
       retrieve: function(property, dflt){
            var storage = get($uid(this)), prop = storage[property];
            if (dflt != null && prop == null) prop = storage[property] = dflt;
            return prop != null ? prop : null;
        },

        store: function(property, value){
            var storage = get($uid(this));
            storage[property] = value;
            return this;
        },

        eliminate: function(property){
            var storage = get($uid(this));
            delete storage[property];
            return this;
        }


    });

})();

// read it.
var link = document.getElement("a");
var uid = link.uid; // will reference the mootools unique id for it

// add an event handler
link.addEvent("click", function(e) {
    console.log("hi");
    this.destroy();
    // see what's left in storage for that element.
    console.log(storage[uid]);

    // storage should be empty.
    console.log(storage);
});

link.getFirst().addEvent("mouseenter", function() {
   console.log("over");
});

// check to see if it is there via element storage API.
console.log(link.retrieve("events").click);

// check to see if it's there via our puncture
console.log(this.storage[uid]);

// see all events in storage, inc child element:
console.info(this.storage);

Все это доказывает, что mootools убирает все, что вам нужно.до тех пор, пока вы не используете встроенные элементы onclick= для элементов, с которыми вы работаете, все будет хорошо.Между сборкой мусора в mootools и браузером вы хорошо защищены.просто знайте, что вы можете сложить несколько событий на одном элементе, если обратные вызовы являются анонимными.

1 голос
/ 01 октября 2011

Интересный вопрос ... прочитайте это: https://developer.mozilla.org/en/DOM/element.addEventListener#Memory_issues

Чтобы удалить прослушиватель событий с помощью jQuery, см. http://api.jquery.com/unbind/

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...