JQuery 或 vanilla Javascript 中的 DOM Mutation 事件

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/7692730/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-26 00:58:40  来源:igfitidea点击:

DOM Mutation event in JQuery or vanilla Javascript

javascriptjquerydommutation-events

提问by aziz punjani

Are there any DOM mutation events in JQuery or in vanilla Javascript that fire cross browser?

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

To clarify, say I have a script on my page which inserts a div into the body. I don't have access to the script and I don't know when the div has been inserted. I was wondering if there's a DOM mutation event that I can add a listener for, to know when an element has been inserted. I know I can use a timer to periodically check for the insertion but, I don't really like the overhead that this would impose.

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

回答by Daniel Mendel

This is certainly a hack, but why not patch the underlying DOM methods used to insert the nodes? There are a couple ways to do this:

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

A. You know what specificelement will be appended to:

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

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

fiddle demo for A

A的小提琴演示

B. You know what typeof element will be appended to:

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

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

fiddle demo for B

B 的小提琴演示

(Note that solution Bis not supported by IE < 8or any other browser which does not support DOM prototypes.)

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

This same technique could just as easily be used on all the underlying DOM mutation functions such as insertBefore, replaceChildor removeChild.

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

That's the general idea, these demos could be adapted for pretty much any other use case -- say you want to cast a wide net and catch alladditions regardless of type ANDmake sure it works across all browserseverything but IE < 8? (see example C below)

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



UPDATE

更新

C.Recursively walk the DOM, swap out the function on every element to trigger a callback, and then apply the same patch to any children being appended.

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>');

fiddle demo for C

C 的小提琴演示

UPDATE 2

更新 2

As Tim Downcommented, the above solution also won't work in IE < 8because appendChildis not a Functionand does not support callor apply. I suppose you could always fall back to the clunky but trusty setIntervalmethod if typeof document.body.appendChild !== 'function'.

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

回答by Kai

There are some deprecatedDOM mutation events, such as DOMNodeInsertedand DOMNodeInsertedIntoDocumentthat still work for me in Chrome 14 and IE9.

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

See an example at http://jsfiddle.net/Kai/WTJq6/

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

See them all on the W3C draft at http://www.w3.org/TR/DOM-Level-3-Events/

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

回答by user1028943

JCADE (JQuery Create and Destroy Events) will do this. It uses behaviorsfor IE and DOM mutation eventsfor other browsers. It does not use timing events and does not wrap JQuery methods like livequery.

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

https://github.com/snesin/jcade

https://github.com/snesin/jcade

    $( document ).create( "a", function( event ) {
      alert( event.target );
    });

回答by Adam Terlson

Not without a plugin, I believe, but I wouldn't be surprised if I'm wrong.

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

My research has found a a few to choose from.

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

Here's one: http://plugins.jquery.com/project/mutation-events

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

Here's another: https://www.adaptavist.com/display/jQuery/Mutation+Events

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

回答by Val

If you are looking for an alternative to this method, here is http://www.jqui.net/jquery-projects/jquery-mutate-official/which can also allow you to add events yourself and keep a watch for almost any change, class name change, height change, width change.

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

回答by Simon Steinberger

The livequeryplugin can be used for this. In version 1.x a timer was used to periodically check for any changes. However, the newer version 2.x branch seems to be working without periodical timeout (untested).

的liveQuery插件可以用于此目的。在 1.xa 版本中,计时器用于定期检查任何更改。但是,较新版本的 2.x 分支似乎可以在没有定期超时的情况下工作(未经测试)。