jQuery - запускает событие, когда элемент удаляется из DOM - PullRequest
201 голосов
/ 04 февраля 2010

Я пытаюсь выяснить, как выполнить код js, когда элемент удален со страницы:

jQuery('#some-element').remove(); // remove some element from the page
/* need to figure out how to independently detect the above happened */

есть ли событие, приспособленное для этого, что-то вроде:

jQuery('#some-element').onremoval( function() {
    // do post-mortem stuff here
});

спасибо.

Ответы [ 14 ]

194 голосов
/ 16 апреля 2012

Для этого вы можете использовать jQuery специальные события .

Во всей простоте

Установка:

(function($){
  $.event.special.destroyed = {
    remove: function(o) {
      if (o.handler) {
        o.handler()
      }
    }
  }
})(jQuery)

Использование:

$('.thing').bind('destroyed', function() {
  // do stuff
})

Приложение к комментариям Пьера и DesignerGuy:

Чтобы не вызывать обратный вызов при вызове $('.thing').off('destroyed'), измените условие if на: if (o.handler && o.type !== 'destroyed') { ... }

113 голосов
/ 26 апреля 2013

Только что проверил, он уже встроен в текущую версию JQuery:

jQuery - v1.9.1

jQuery UI - v1.10.2

$("#myDiv").on("remove", function () {
    alert("Element was removed");
})

Важно : это функциональность JQuery UI скрипт (не JQuery), поэтому вам нужно загрузить оба скрипта (jquery и jquery-ui), чтобы он работал Вот пример: http://jsfiddle.net/72RTz/

47 голосов
/ 08 августа 2011

Вы можете привязаться к событию DOMNodeRemoved (часть спецификации DOM уровня 3 WC3).

Работает в IE9, последних версиях Firefox и Chrome.

Пример:

$(document).bind("DOMNodeRemoved", function(e)
{
    alert("Removed: " + e.target.nodeName);
});

Вы также можете получать уведомления при вставке элементов путем привязки к DOMNodeInserted

37 голосов
/ 04 февраля 2010

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

(function() {
    var ev = new $.Event('remove'),
        orig = $.fn.remove;
    $.fn.remove = function() {
        $(this).trigger(ev);
        return orig.apply(this, arguments);
    }
})();

$('#some-element').bind('remove', function() {
    console.log('removed!');
    // do pre-mortem stuff here
    // 'this' is still a reference to the element, before removing it
});

// some other js code here [...]

$('#some-element').remove();

Примечание: некоторые проблемы с этим ответом были изложены другими авторами.

  1. Это не будет работать, когда узел удаляется с помощью html() replace() или других методов jQuery
  2. Это событие вспыхивает
  3. также удаляются переопределения jQuery UI

Наиболее элегантное решение этой проблемы выглядит следующим образом: https://stackoverflow.com/a/10172676/216941

32 голосов
/ 03 ноября 2011

Перехват .remove() не лучший способ справиться с этим, так как существует множество способов удалить элементы со страницы (например, с помощью .html(), .replace() и т. Д.).

Чтобы предотвратить различные угрозы утечки памяти, внутренне jQuery попытается вызвать функцию jQuery.cleanData() для каждого удаленного элемента независимо от метода, использованного для его удаления.

См. Этот ответ для более подробной информации: утечки памяти javascript

Таким образом, для достижения наилучших результатов вам следует подключить функцию cleanData, которая является именно тем, что делает плагин jquery.event.destroyed :

http://v3.javascriptmvc.com/jquery/dist/jquery.event.destroyed.js

7 голосов
/ 28 сентября 2011

Для тех, кто использует jQuery UI:

Пользовательский интерфейс jQuery переопределил некоторые методы jQuery для реализации события remove, которое обрабатывается не только при явном удалении данного элемента, но также и при удалении элемента из DOM любыми самоочищающимися методами jQuery например, replace, html и т. д.). По сути, это позволяет вам перехватывать те же события, которые запускаются, когда jQuery «очищает» события и данные, связанные с элементом DOM.

Джон Резиг указал , что он открыт для идеи реализации этого события в будущей версии ядра jQuery, но я не уверен, где оно сейчас стоит.

4 голосов
/ 15 февраля 2017

Решение без использования jQuery UI

( Я извлек это расширение из инфраструктуры jQuery UI )

Работает с: empty() и html() и remove()

$.cleanData = ( function( orig ) {
    return function( elems ) {
        var events, elem, i;
        for ( i = 0; ( elem = elems[ i ] ) != null; i++ ) {
            try {

                // Only trigger remove when necessary to save time
                events = $._data( elem, "events" );
                if ( events && events.remove ) {
                    $( elem ).triggerHandler( "remove" );
                }

            // Http://bugs.jquery.com/ticket/8235
            } catch ( e ) {}
        }
        orig( elems );
    };
} )( $.cleanData );

С этим решением вы также можете отсоединить обработчик событий.

$("YourElemSelector").off("remove");
<Ч />

Попробуй! - Пример

$.cleanData = (function(orig) {
  return function(elems) {
    var events, elem, i;
    for (i = 0;
      (elem = elems[i]) != null; i++) {
      try {

        // Only trigger remove when necessary to save time
        events = $._data(elem, "events");
        if (events && events.remove) {
          $(elem).triggerHandler("remove");
        }

        // Http://bugs.jquery.com/ticket/8235
      } catch (e) {}
    }
    orig(elems);
  };
})($.cleanData);


$("#DivToBeRemoved").on("remove", function() {
  console.log("div was removed event fired");
});

$("p").on("remove", function() {
  console.log("p was removed event fired");
});

$("span").on("remove", function() {
  console.log("span was removed event fired");
});

// $("span").off("remove");

$("#DivToBeRemoved").on("click", function() {
  console.log("Div was clicked");
});

function RemoveDiv() {
  //       $("#DivToBeRemoved").parent().html("");    
  $("#DivToBeRemoved").remove();
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<h3>OnRemove event handler attached to elements `div`, `p` and `span`.</h3>
<div class="container">
  <br>
  <button onclick="RemoveDiv();">Click here to remove div below</button>
  <div id="DivToBeRemoved">
    DIV TO BE REMOVED 
    contains 1 p element 
    which in turn contains a span element
    <p>i am p (within div)
      <br><br><span>i am span (within div)</span></p>
  </div>
</div>

Дополнительно Демонстрация - jsBin

4 голосов
/ 29 мая 2014

Мне не удалось заставить этот ответ работать с отменой привязки (несмотря на обновление , см. Здесь ), но я смог найти способ обойти это. Ответ состоял в том, чтобы создать специальное событие destroy_proxy, которое вызвало бы уничтоженное событие. Вы помещаете прослушиватель событий в «destroy_proxy» и «destroy», затем, когда вы хотите отменить привязку, вы просто отмените привязку «destroy»:

var count = 1;
(function ($) {
    $.event.special.destroyed_proxy = {
        remove: function (o) {
            $(this).trigger('destroyed');
        }
    }
})(jQuery)

$('.remove').on('click', function () {
    $(this).parent().remove();
});

$('li').on('destroyed_proxy destroyed', function () {
    console.log('Element removed');
    if (count > 2) {
        $('li').off('destroyed');
        console.log('unbinded');
    }
    count++;
});

Вот скрипка

3 голосов
/ 11 декабря 2012

Мне нравится ответ mtkopone, использующий специальные события jQuery, но учтите, что он не работает а) когда элементы отсоединяются вместо удаления или б) когда некоторые старые не-jquery библиотеки используют innerHTML для уничтожения ваших элементов

1 голос
/ 01 июля 2018

Событие "удалить" из jQuery работает нормально, без добавления. Возможно, будет более надежным вовремя использовать простой трюк вместо исправления jQuery.

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

Предположим, у нас есть таблица с ячейками, соответствующими ценам, и вам нужно показать только последнюю цену: Это селектор, который срабатывает при удалении ценовой ячейки (у нас есть кнопка в каждой строке таблицы, которая здесь не показана)

$('td[validity="count_it"]').on("remove", function () {
    $(this).attr("validity","do_not_count_it");
    update_prices();
});

А вот функция, которая находит последнюю цену в таблице, не учитывая последнюю, если она была удалена. Действительно, когда срабатывает событие «удалить» и когда вызывается эта функция, элемент еще не удален.

function update_prices(){
      var mytable=$("#pricestable");
      var lastpricecell = mytable.find('td[validity="count_it"]').last();
}

В конце функция update_prices () работает нормально, и после этого элемент DOM удаляется.

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