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

Я создавал большое одностраничное приложение и недавно изучал утечки памяти в JS. И я думаю, что у меня утечка памяти, потому что, поскольку я использую функцию "Профили" (Snapshot) в Chrome, я вижу, что у меня много отдельных элементов DOM.

Вот упрощенная версия моей установки:

<div id="container">
  <div class="buttons">
    <a class=".btn" href="/someurl/"> Button A</a>
    <a class=".btn" href="/someurl/"> Button B</a>
    <a class=".btn" href="/someurl/"> Button C</a>
  </div>

  <div class="ajaxHolder"></div>
</div>

Итак, если пользователь нажимает кнопку A, например, я бы использовал вызов AJAX для загрузки содержимого в .ajaxHolder. Что-то вроде этого:

//This is the content...
<div class="contentA">
  <p>some text...</p>
  <input type="checkbox" class="checkbox">
  <input type="checkbox" class="checkbox">
  <input type="checkbox" class="checkbox">
  <input type="checkbox" class="checkbox">
</div>

У меня также есть две функции внутри моего файла MAIN script. Это будет так:

//Click event bound to a.btn which tigger the ajax call
$(.buttons).on('click', '.btn', function(){ 
  //Do ajax here...
  //on success...
  var holder = $(".ajaxHolder");
  holder.children().off().remove(); // Is this the way to do this??
  holder.off().empty(); //I don't think I need .off() here, but I guess it can't hurt...
  holder.append(ajaxSuccessData);
});

Пока все хорошо. Но теперь, когда содержимое загружено, у меня также есть эта функция внутри моего MAIN script файла:

//So here, I am binding an event to the checkboxes...
$(".ajaxHolder").on('change', '.checkbox', function(){
  //Do something...
});

Итак, теперь, если пользователь нажимает кнопку B, например, .ajaxHolder опустеет, но все те события, привязанные к моим флажкам, похоже, скручиваются, потому что они появляются в отдельном дереве DOM.

Что мне здесь не хватает? Как я могу убедиться, что у меня нет каких-либо отдельных элементов DOM, в одностраничном приложении, выполняющемся следующим образом?

ВОПРОС БОНУСА: У меня много событий, связанных так:

$(".ajaxHolder").on('someEvent...','.someClass....', someFunction());

То есть все всегда привязано к моему .ajaxHolder, потому что я должен использовать делегирование событий, поскольку .ajaxHolder всегда будет существовать, тогда как другие загружаемые элементы не всегда будут существовать, поэтому я не могу просто сделать $(button).on('click')... и т.д.

Итак, это правильный способ сделать это? Есть ли ограничение на количество вещей, которые я могу прикрепить к этому .ajaxHolder, или нет проблем с этим?

EDIT: вот изображение моей консоли, если это вообще помогает.

введите описание изображения здесь

Ответ 1

Не уверен, что это все еще актуально, но из изображения консоли, которое я собираю, вы используете всплывающие подсказки для начальной загрузки, и они, похоже, содержат ссылку на DOM node. Я предлагаю вам вызвать метод destroy с помощью API

Ответ 2

Событие jQuery unbinding и удаление элементов может быть dong со следующими методами:

$. off()

$. remove()

Ответ 3

Лучший способ сделать это - развязать все прослушиватели событий с помощью $(selector).off(); метод, а затем удаление элемента с помощью $(selector).remove();

Это остановит все утечки памяти из-за обработчиков событий.