代码之家  ›  专栏  ›  技术社区  ›  sa125

jquery-从dom中移除元素时的触发器事件

  •  199
  • sa125  · 技术社区  · 15 年前

    我正在尝试在从页面中移除元素时如何执行一些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 回复  |  直到 7 年前
        1
  •  112
  •   Philipp Munin    11 年前

    刚检查过,它已经内置在当前版本的jquery中:

    jQuery—V1.9

    jquery用户界面-v1.10.2

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

    重要的 :这是的功能 jQuery UI 脚本(不是jquery),所以您必须同时加载两个脚本(jquery和jquery ui)才能使其工作。以下是示例: http://jsfiddle.net/72RTz/

        2
  •  194
  •   mtkopone    12 年前

    你可以使用 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') { ... }

        3
  •  45
  •   Adam    14 年前

    可以绑定到domnoderemoved事件(dom级别3 wc3规范的一部分)。

    适用于IE9,最新版本的火狐和Chrome。

    例子:

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

    还可以通过绑定来获取元素插入时的通知 DOMNodeInserted

        4
  •  37
  •   Community CDub    8 年前

    没有用于删除元素的内置事件,但是您可以通过假扩展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用户界面也覆盖remove

    这个问题最优雅的解决方案似乎是: https://stackoverflow.com/a/10172676/216941

        5
  •  32
  •   Community CDub    8 年前

    挂钩 .remove() 不是处理此问题的最佳方法,因为有许多方法可以从页面中删除元素(例如使用 .html() , .replace() 等)。

    为了防止各种内存泄漏危险,内部jquery将尝试调用函数 jQuery.cleanData() 对于每个被移除的元素,不管移除它的方法如何。

    有关详细信息,请参阅此答案: javascript memory leaks

    因此,为了获得最佳效果,您应该 cleanData 函数,这正是 jquery.event.destroyed 插件:

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

        6
  •  7
  •   StriplingWarrior    13 年前

    对于使用jquery用户界面的用户:

    jquery UI已重写一些jquery方法以实现 remove 事件,它不仅在显式删除给定元素时得到处理,而且在通过任何自清理jquery方法(例如 replace , html 等等)。这基本上允许您在jquery“清理”与dom元素相关联的事件和数据时,将一个钩子放入相同的事件中。

    John Resig has indicated 他对在未来版本的jquery核心中实现这个事件的想法持开放态度,但我不确定它目前的位置。

        7
  •  4
  •   Community CDub    8 年前

    我不能得到 this answer 使用解除绑定(尽管更新了 see here ,但能够找到解决办法。答案是创建一个“销毁代理”特殊事件,触发一个“销毁”事件。您将事件侦听器同时置于“destroyed\u proxy”和“destroyed”上,然后当您要解除绑定时,只需解除绑定“destroyed”事件:

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

    这里是一个 fiddle

        8
  •  4
  •   Legends    7 年前

    不使用jquery用户界面的解决方案

    ( 我已经从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>

    附加的 Demo - jsBin

        9
  •  3
  •   Charon ME    12 年前

    我喜欢mtkopone使用jquery特殊事件的答案,但请注意,它不起作用a)当分离元素而不是移除元素时,或b)当一些旧的非jquery库使用innerhtml来销毁元素时

        10
  •  1
  •   Fenton    15 年前

    我不确定是否有这样的事件句柄,所以您必须保留一个DOM的副本,并在某种轮询循环中与现有的DOM进行比较——这可能非常糟糕。但是Firebug会这样做——如果您检查HTML并运行一些DOM更改,它会在很短时间内突出显示Firebug控制台中黄色的更改。

    或者,您可以创建一个删除函数…

    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");
    
        11
  •  1
  •   Buzogany Laszlo    8 年前

    这是如何创建jquery 实时删除侦听器 :

    $(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)
      }
    });
    
        12
  •  1
  •   philippe    7 年前

    jquery中的“remove”事件可以正常工作,无需添加。使用一个简单的技巧,而不是修补jquery,可能在时间上更可靠。

    只需在要从DOM中删除的元素中修改或添加属性。因此,您可以触发任何更新函数,它只会忽略要销毁的途中的元素,属性为“不要计算”。

    假设我们有一个表,其中单元格与价格相对应,并且您只需要显示最后一个价格: 这是删除价格单元格时要触发的选择器(我们在表格的每一行中都有一个按钮,这里没有显示)

    $('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元素。

        13
  •  0
  •   Patryk M    13 年前

    引用@david answer:

    当你想用另一个函数来做soo时,例如html(),在我的例子中,不要忘记在新函数中添加return:

    (function() {
        var ev = new $.Event('html'),
            orig = $.fn.html;
        $.fn.html = function() {
            $(this).trigger(ev);
            return orig.apply(this, arguments);
        }
    })();
    
        14
  •  0
  •   Matas Vaitkevicius user3782709    11 年前

    这个。

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