Нужно ли удалять прослушиватели событий javascript перед удалением элемента, к которому они прикреплены? - PullRequest
8 голосов
/ 16 июля 2009

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

Необходимо (или предлагается) отменить регистрацию любых обработчиков событий, существующих в форме и ее элементах? Если так, какой самый простой способ удалить всех слушателей в коллекции элементов? Каковы последствия не делать этого? Я использую Prototype, если это важно.

Вот что я на самом деле делаю. У меня есть простая форма, как это:

<form id="form">
  <input type="text" id="foo"/>
  <input type="text" id="bar"/>
</form>

Я наблюдаю различные события на входах, например ::100100

$('foo').observe('keypress', onFooKeypress);
$('bar').observe('keypress', onBarKeypress);

и т.д.

Форма отправляется через AJAX, а ответ является новой копией формы. Я заменяю старую форму копией новой, делая что-то вроде $('form').replace(newForm). Я накапливаю кучу событий?

Ответы [ 3 ]

4 голосов
/ 16 июля 2009

События, которые не являются незарегистрированными, не могут автоматически освобождать их память. Это особенно проблема в старых версиях IE.

Прототип имел систему автоматической сборки мусора для этого, но этот метод был удален в версии 1.6. Это задокументировано здесь . Я не знаю, означает ли удаление метода, что сборка мусора больше не выполняется, или метод просто больше не доступен для общественности. Также обратите внимание, что он вызывался только при выгрузке страницы, что означает, что если ваши пользователи остаются на одной и той же странице в течение длительного времени при выполнении большого количества обновлений AJAX и DOM, память может протекать в недопустимой степени даже при посещении одной страницы.

3 голосов
/ 27 июля 2009

Да, немного.Недостаточно, чтобы быть огромной проблемой, но старые версии IE будут протекать при таких обстоятельствах.

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

Однако, если пользователь будет какое-то время оставаться на этой странице, использование памяти будет накапливаться в течение жизни страницы.У вас есть несколько вариантов:

  1. Прослушивать события на предке формы, который никогда не будет заменен.Затем в вашем обработчике проверьте, откуда пришло событие.(т. е. «делегирование события»)

  2. Явно отмените регистрацию всех ваших вызовов перед вызовом Element#replace.В вашем примере вы должны выполнить:

    $('foo', 'bar').each(Element.stopObserving);
    

Это эквивалентно вызову stopObserving без аргументов, что приводит к удалению обработчиков all для данного элемента.

Я бы порекомендовал вариант 1.

(Мы говорили об автоматическом удалении слушателя в будущей версии Prototype в составе Element#update и Element#replace,но это компромисс производительности.)

0 голосов
/ 16 июля 2009

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

...