JQuery 或普通 Javascript 中是否存在跨浏览器触发的 DOM 突变事件?
为了澄清,假设我的页面上有一个脚本,它将一个 div 插入到正文中。我无权访问该脚本,也不知道 div 何时被插入。我想知道是否有一个 DOM 突变事件,我可以为其添加监听器,以了解何时插入元素。我知道我可以使用计时器定期检查插入情况,但是我不太喜欢这会带来的开销。
最佳答案
这当然是一种 hack,但为什么不修补用于插入节点的底层 DOM 方法呢?有几种方法可以做到这一点:
A。您知道将附加什么特定元素:
var c = document.getElementById('#container');
c.__appendChild = c.appendChild;
c.appendChild = function(){
alert('new item added');
c.__appendChild.apply(c, arguments);
}
B。您知道将附加到什么类型元素:
HTMLDivElement.prototype.__appendChild = HTMLDivElement.prototype.appendChild;
HTMLDivElement.prototype.appendChild = function(){
alert('new item added');
HTMLDivElement.prototype.__appendChild(this,arguments);
}
(请注意,IE < 8
或任何其他不支持 DOM 原型(prototype)的浏览器不支持解决方案 B。)
同样的技术可以轻松地用于所有底层 DOM 突变函数,例如 insertBefore
, replaceChild
或removeChild
.
这是总体思路,这些演示可以适用于几乎任何其他用例 - 假设您想广撒网并捕获所有添加内容,无论类型如何和 确保它适用于所有浏览器,除了 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>');
更新2
如Tim Down评论说,上述解决方案在 IE < 8
中也不起作用因为appendChild
不是Function
并且不支持call
或apply
。我想你总是可以回到笨重但值得信赖的 setInterval
方法如果 typeof document.body.appendChild !== 'function'
.
关于javascript - JQuery 或 vanilla Javascript 中的 DOM Mutation 事件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7692730/