jQuery-событие триггера при удалении элемента из DOM

Я пытаюсь выяснить, как выполнить некоторый код 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 ответов


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

jQuery-v1.9.1

jQuery UI-v1.10.2

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

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


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

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

настройка:

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

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

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

добавление к ответу на комментарии Pierre и DesignerGuy:

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


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

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

пример:

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

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


нет встроенного события для удаления элементов,но вы можете создать его с помощью метода удаления 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. это событие пузыри вверх!--10-->
  3. jQuery UI переопределяет remove, а также

наиболее элегантное решение этой проблемы, кажется: https://stackoverflow.com/a/10172676/216941


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

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

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

поэтому, для достижения наилучших результатов, вы должны подключить cleanData функции, что и С помощью jQuery.событие.уничтожен плагин делает:

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


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

jQuery UI переопределил некоторые методы jQuery для реализации remove событие, которое обрабатывается не только при явном удалении данного элемента, но и при удалении элемента из DOM любыми самоочищающимися методами jQuery (например,replace, html, etc.). Это в основном позволяет вам подключать те же события, которые запускаются, когда jQuery "очищает" события и данные, связанные с DOM элемент.

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


Я не мог получить ответ для работы с unbinding (несмотря на обновление посмотреть здесь), но смог найти способ обойти это. Ответ был для создания destroy_proxy' особое событие, которое вызвало "разрушается" событие. Вы ставите прослушиватель событий как на "destroyed_proxy", так и на "destroyed", а затем, когда вы хотите отменить привязку, вы просто отменяете "destroyed" event:

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++;
});

здесь скрипка


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

(я извлек это расширение из jQuery UI framework)

работает: 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


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


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

кроме того, вы можете создать функцию remove...

var removeElements = function(selector) {
    var elems = jQuery(selector);

    // Your code to notify the removal of the element here...
    alert(elems.length + " elements removed");

    jQuery(selector).remove();
};

// Sample usage
removeElements("#some-element");
removeElements("p");
removeElements(".myclass");

вот как создать jQuery live удалить слушателя:

$(document).on('DOMNodeRemoved', function(e)
{
  var $element = $(e.target).find('.element');
  if ($element.length)
  {
    // do anything with $element
  }
});

или:

$(document).on('DOMNodeRemoved', function(e)
{
  $(e.target).find('.element').each(function()
  {
    // do anything with $(this)
  }
});

ссылка на @David ответ:

когда вы хотите сделать soo с другой функцией, например. html () как и в моем случае, не забудьте добавить return в новую функцию:

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

этого.

$.each(
  $('#some-element'), 
        function(i, item){
            item.addEventListener('DOMNodeRemovedFromDocument',
                function(e){ console.log('I has been removed'); console.log(e);
                })
         })

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

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

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

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

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

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

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