jQuery - 当DOM改变时运行函数

6
我迄今为止一直在使用livequery,它可以工作,但会使页面浏览速度变慢。因此,我正在尝试寻找另一种替代方案。
我附加了一个函数,在具有特定类的元素上运行一些ajax,例如:
$(".blah").each(function(){
  $.ajax({
      ...
      success: function(data) { 
        $(this).removeClass(".blah");
        // do other stuff
      }
  });
});

现在我有几个钩子事件挂在不同的元素上,可以向DOM中添加HTML,例如:
$(".button").click(function(){
  $.ajax({
      ...
      success: function(data) { 
        $(this).append(data);
        // here, new elements with ".blah" class could be inserted in the DOM
        // the event above won't be fired...
      }
  });
});

我该如何让上面的第一个ajax函数在DOM在其他事件中更新时运行?
更新:
我还发现了这个插件:http://www.thunderguy.com/semicolon/2007/08/14/elementready-jquery-plugin/ 你认为它会是更好的解决方案吗?从快速查看中,似乎是因为它允许您设置“轮询”间隔,如果将其设置为1秒或某些内容,则可能会减少CPU使用率。我正在测试它 :)
更新2:
不幸的是,由于某种奇怪的原因,它仅适用于元素ID :(
4个回答

14

大部分主流浏览器(但遗憾的是不包括 IE <= 8)支持DOM 变动事件(可以参考 MDN)。如果你只关心节点被添加到 DOM 中,可以使用 DOMNodeInserted 事件。如果你希望得知任何 DOM 更改,可以使用万能的 DOMSubtreeModified 事件。

例如:

document.addEventListener("DOMNodeInserted", function(evt) {
    alert("Node inserted. Parent of inserted node: " + evt.relatedNode.nodeName);
}, false);

document.body.appendChild( document.createElement("div") );

2012年12月13日更新

DOM修改事件现已过时,浏览器正在逐渐转向变异观察器。目前最明智的策略似乎是使用变异观察器,并回退到变异事件。


2

这是真的,因为新元素没有绑定到回调事件,它们只是全新的元素。我建议在创建新元素后立即绑定事件(即在ajax成功函数内部):

    $(".blah").each(function(){
      $.ajax({
          ...
          success: function(data) { 
            $(this).removeClass(".blah");
            // add handlers to new elements with class "button"
            $(this).find('.button').click(function() {  
                     $.ajax({
                          success: function(data) { 
                            $(this).append(data);
                          });
          }
      });
    }

1
IE9+, FF和Chrome:
var observeDOM = (function(){
    var MutationObserver = window.MutationObserver || window.WebKitMutationObserver,
        eventListenerSupported = window.addEventListener;

    return function(obj, callback){
        if( MutationObserver ){
            // define a new observer
            var obs = new MutationObserver(function(mutations, observer){
                if( mutations[0].addedNodes.length || mutations[0].removedNodes.length )
                    callback();
            });
            // have the observer observe foo for changes in children
            obs.observe( obj, { childList:true, subtree:true });
        }
        else if( eventListenerSupported ){
            obj.addEventListener('DOMNodeInserted', callback, false);
            obj.addEventListener('DOMNodeRemoved', callback, false);
        }
    }
})();

observeDOM( $('#dom_element')[0] ,function(){ 
    console.log('dom changed');
});

1
我也遇到了这样的问题。据我所知,没有真正的方法可以在DOM更改时运行某些东西。我通过两种不同的方法来解决这个问题:
  1. 每秒钟调用一次函数或在用户移动鼠标时触发函数。如果处理不当,这两种方法都可能导致减速。
  2. 在ajax完成时调用一个函数。只需在成功部分中调用doAjax(),每次完成查询时都会调用它。

您还可以将第一个ajax查询绑定到body标记,因此每当用户单击某个内容时,ajax事件就会触发,然后检查是否满足正确的条件。

编辑:这可能有效。添加$("BODY ID/CLASS").change(function () {}); 我对jQuery并不是很熟悉,所以不能完全确定。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接