DOM中的DOM突变事件在jQuery或者是vanilla Javascript中 [英] DOM Mutation event in JQuery or vanilla Javascript

查看:114
本文介绍了DOM中的DOM突变事件在jQuery或者是vanilla Javascript中的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述



为了澄清,说我在我的页面上插入一个脚本,插入一个div进入身体。我无法访问该脚本,我不知道div何时被插入。我想知道是否有一个DOM突变事件,我可以添加一个监听器,以了解何时插入一个元素。我知道我可以使用定时器来定期检查插入,但是我并不喜欢这样做的开销。

解决方案

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



A 。你知道什么具体元素将被追加到:

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

小提琴演示 A



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

  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 replaceChild removeChild



这是一般的想法,这些演示可以适应几乎任何其他的用例 - 例如你想投射广泛的网络和捕获所有添加,而不管类型 AND 是否确保它可以在所有浏览器之间运行,但 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 因为 appendChild 不是函数并且不支持 申请。我想你可能总是回到笨重但可靠的 setInterval 方法,如果 typeof document.body.appendChild!=='function'


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

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.

解决方案

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:

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

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

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

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

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? (see example C below)


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.

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

UPDATE 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. I suppose you could always fall back to the clunky but trusty setInterval method if typeof document.body.appendChild !== 'function'.

这篇关于DOM中的DOM突变事件在jQuery或者是vanilla Javascript中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆