简体   繁体   English

JQuery或vanilla Javascript中的DOM Mutation事件

[英]DOM Mutation event in JQuery or vanilla Javascript

Are there any DOM mutation events in JQuery or in vanilla Javascript that fire cross browser? JQuery中是否有任何DOM突变事件或者是跨浏览器的vanilla Javascript?

To clarify, say I have a script on my page which inserts a div into the body. 为了澄清,我说我的页面上有一个脚本,它将div插入到正文中。 I don't have access to the script and I don't know when the div has been inserted. 我无法访问脚本,我不知道何时插入了div。 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. 我想知道是否有一个DOM突变事件,我可以添加一个监听器,以了解何时插入了一个元素。 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. 我知道我可以使用计时器来定期检查插入,但是,我真的不喜欢这会带来的开销。

This is certainly a hack, but why not patch the underlying DOM methods used to insert the nodes? 这肯定是一个黑客,但为什么不修补用于插入节点的底层DOM方法? There are a couple ways to do this: 有几种方法可以做到这一点:

A . A。 You know what specific element 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 . B。 You know what type of 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 B is not supported by IE < 8 or any other browser which does not support DOM prototypes.) (请注意, IE < 8或任何其他不支持DOM原型的浏览器不支持解决方案B.

This same technique could just as easily be used on all the underlying DOM mutation functions such as insertBefore , replaceChild or removeChild . 同样的技术可以很容易地用于所有底层DOM变异函数,例如insertBeforereplaceChildremoveChild

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 all additions regardless of type AND make sure it works across all browsers everything but IE < 8 ? 这是一般的想法,这些演示可以适用于几乎任何其他用例 - 比如你想要投射一个宽网并捕获所有添加物,无论类型确保它适用于所有浏览器除了IE < 8 所有东西? (see example C below) (见下面的例子C)


UPDATE 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 Down commented, the above solution also won't work in IE < 8 because appendChild is not a Function and does not support call or apply . 正如Tim Down评论的那样,上述解决方案在IE < 8也不起作用,因为appendChild不是一个Function ,不支持callapply I suppose you could always fall back to the clunky but trusty setInterval method if typeof document.body.appendChild !== 'function' . 如果typeof document.body.appendChild !== 'function'我想你总是可以回到笨重而可靠的setInterval方法。

There are some deprecated DOM mutation events, such as DOMNodeInserted and DOMNodeInsertedIntoDocument that 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/ 请参阅W3C草案中的所有内容, 网址http://www.w3.org/TR/DOM-Level-3-Events/

JCADE (JQuery Create and Destroy Events) will do this. JCADE(JQuery创建和销毁事件)将执行此操作。 It uses behaviors for IE and DOM mutation events for other browsers. 它为其他浏览器使用IE和DOM突变事件的 行为 It does not use timing events and does not wrap JQuery methods like livequery. 它不使用计时事件,也不包括像livequery这样的JQuery方法。

https://github.com/snesin/jcade https://github.com/snesin/jcade

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

Not without a plugin, I believe, but I wouldn't be surprised if I'm wrong. 我相信,并非没有插件,但如果我错了,我不会感到惊讶。

My research has found aa 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

如果您正在寻找此方法的替代方法,请访问http://www.jqui.net/jquery-projects/jquery-mutate-official/ ,它还可以让您自己添加事件并随时关注任何更改,班级名称变更,身高变化,宽度变化。

The livequery plugin can be used for this. livequery插件可用于此目的。 In version 1.xa timer was used to periodically check for any changes. 在版本1.xa中,计时器用于定期检查是否有任何更改。 However, the newer version 2.x branch seems to be working without periodical timeout (untested). 但是,较新的版本2.x分支似乎没有周期性超时(未经测试)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM