JQuery 或 vanilla Javascript 中的 DOM Mutation 事件

IT技术 javascript jquery dom mutation-events
2021-01-15 19:01:44

在 JQuery 或 vanilla Javascript 中是否有任何 DOM 突变事件会触发跨浏览器?

澄清一下,假设我的页面上有一个脚本,它在正文中插入一个 div。我无权访问脚本,也不知道 div 何时插入。我想知道是否有我可以添加侦听器的 DOM 突变事件,以了解何时插入元素。我知道我可以使用计时器来定期检查插入,但是,我真的不喜欢这会带来的开销。

6个回答

这当然是一个 hack,但为什么不修补用于插入节点的底层 DOM 方法呢?有几种方法可以做到这一点:

一个您知道将附加到哪些特定元素:

var c = document.getElementById('#container');
c.__appendChild = c.appendChild;
c.appendChild = function(){
     alert('new item added');
     c.__appendChild.apply(c, arguments); 
}

A的小提琴演示

你知道什么类型的元素将被附加到:

HTMLDivElement.prototype.__appendChild = HTMLDivElement.prototype.appendChild;
HTMLDivElement.prototype.appendChild = function(){
    alert('new item added');
    HTMLDivElement.prototype.__appendChild(this,arguments); 
}

B 的小提琴演示

(请注意,解决方案B不受IE < 8或任何其他不支持 DOM 原型的浏览器的支持。)

同样的技术可以很容易地用于所有底层 DOM 突变函数,例如insertBefore,replaceChildremoveChild

这是一般的想法,这些演示几乎可以适用于任何其他用例 - 假设您想撒网并捕获所有添加内容,而不管类型如何并确保它适用于所有浏览器,IE < 8? (参见下面的示例 C)


更新

C.递归遍历 DOM,交换每个元素上的函数以触发回调,然后将相同的补丁应用于任何被附加的子元素。

var DOMwatcher = function(root, callback){
  var __appendChild = document.body.appendChild;

  var patch = function(node){
    if(typeof node.appendChild !== 'undefined' && node.nodeName !== '#text'){
      node.appendChild = function(incomingNode){
        callback(node, incomingNode);
        patch(incomingNode);
        walk(incomingNode);
        __appendChild.call(node, incomingNode);
      };
    }
    walk(node);  
  };

  var walk = function(node){
    var i = node.childNodes.length;
    while(i--){
      patch(node.childNodes[i]);
    }
  };

  patch(root);

};

DOMwatcher(document.body, function(targetElement, newElement){ 
   alert('append detected');    
});

$('#container ul li').first().append('<div><p>hi</p></div>');
$('#container ul li div p').append('<a href="#foo">bar</a>');

C 的小提琴演示

更新 2

正如Tim Down评论的那样,上述解决方案也无法使用,IE < 8因为appendChildis not aFunction并且不支持callor apply我想setInterval如果typeof document.body.appendChild !== 'function'.

@TimDown 射击!您是对的,在appendChild不是的浏览器中,Function此解决方案将失败,因为它不响应callapply很好,我已经更新了答案以反映这一点。但是,您会发现上面的代码在 IE 8 中确实有效。
2021-03-21 19:01:44
这在 IE < 9 中不起作用,并且通常是狡猾的,因为诸如appendChild()不需要是Function对象的宿主方法(并且实际上不在 IE < 9 中)。
2021-03-22 19:01:44
如果您正在寻找此方法的替代方法,请访问jqui.net/jquery-projects/jquery-mutate-official,它也可以让您自己添加事件并密切关注几乎所有更改、类名更改、高度更改,宽度变化。
2021-03-27 19:01:44
令人着迷,也令人恐惧。+1!
2021-04-08 19:01:44
喔好吧。我对 IE 8 不确定,我承认。
2021-04-10 19:01:44

有一些已弃用的DOM 突变事件,例如DOMNodeInsertedDOMNodeInsertedIntoDocument在 Chrome 14 和 IE9 中仍然适用于我。

请参阅http://jsfiddle.net/Kai/WTJq6/ 上的示例

http://www.w3.org/TR/DOM-Level-3-Events/的 W3C 草案中查看所有这些内容

很高兴了解 IE,因为我不经常使用它。顺便说一句,OT:我昨天发现了你的 Rangy lib——它太棒了,ty。:)
2021-03-28 19:01:44
IE 9 是第一个具有 DOM 突变事件的 IE 版本,因此这在 IE < 9 中不起作用。虽然这些事件已被弃用,但其替换规范尚未完成,因此它们不会消失虽然还。
2021-03-30 19:01:44

JCADE(JQuery 创建和销毁事件)将执行此操作。为其他浏览器使用IE 和DOM 突变事件的行为它不使用计时事件,也不像 livequery 那样包装 JQuery 方法。

https://github.com/snesin/jcade


    $( 文档 ).create( "a", function( event ) {
      警报(事件。目标);
    });

我相信不是没有插件,但如果我错了,我不会感到惊讶。

我的研究发现了一些可供选择。

这是一个:http : //plugins.jquery.com/project/mutation-events

这是另一个:https : //www.adaptavist.com/display/jQuery/Mutation+Events

嗯,糟透了。我承认我没有尝试过,所以我不能真正谈论它们是如何工作的。对不起。
2021-04-05 19:01:44
这看起来很有希望,直到我查看脚本代码并意识到他们没有使用 jQuery 将 div 插入到 DOM 中。
2021-04-10 19:01:44

如果您正在寻找此方法的替代方法,请访问http://www.jqui.net/jquery-projects/jquery-mutate-official/,它也可以让您自己添加事件并留意几乎所有更改,类名改变,高度改变,宽度改变。