在firefox, webkit中我们可以使用DOMNodeInsertedIntoDocument事件,但这个事件很快变废弃了,虽然浏览器还是很有节操地支持它们,但哪一天不在也很难说。比如说firefox22已经不支持了,IE则始终不支持此事件。
这里有个脚本,可以判定浏览器是否支持变动事件
var mutations = (function (document) { // (C) WebReflection - Mit Style License var type = [ "DOMSubtreeModified", "DOMNodeInserted", "DOMNodeRemoved", "DOMNodeRemovedFromDocument", "DOMNodeInsertedIntoDocument", "DOMAttrModified", "DOMCharacterDataModified" ], documentElement = document.documentElement, method = "EventListener", data = "deleteData", p = document.createElement("p"), mutations = {}, i ; function check(addOrRemove) { for (i = type.length; i--;) { p[addOrRemove](type[i], cb, false); documentElement[addOrRemove](type[i], cb, false); } } function cb(e) { mutations[e.type] = true; } check("add" + method); documentElement.insertBefore( p, documentElement.lastChild ); p.setAttribute("i", i); p = p.appendChild(document.createTextNode(i)); data in p && p[data](0, 1); documentElement.removeChild(p = p.parentNode); check("remove" + method); return (p = mutations); }(document));
在《Detect DOM Node Insertions with JavaScript and CSS Animations》这篇文章中,作者提供了一个方法,教我们利用keyframe CSS3开始动画事件来监听节点的插入。
<script> window.onload = function() { var count = 0, insertListener = function(event){ console.warn("Another node has been inserted! ", event); if (event.animationName == "nodeInserted") { event.target.textContent = "Element " + count++ + " has been injected!"; } } document.addEventListener("animationstart", insertListener, false); // standard + firefox document.addEventListener("MSAnimationStart", insertListener, false); // IE document.addEventListener("webkitAnimationStart", insertListener, false); // Chrome + Safari // Insert a new element setInterval(function(){ document.getElementById("parentElement").appendChild(document.createElement("li")) }, 2000); }; </script>
var WeakMap = WeakMap || function(){ /*!(C) WebReflection - Mit Style !*/ // WARNING: DO NOT FORGET TO DELETE KEYS WHEN POSSIBLE // MEMORY GREEDY, UNSAFE, BROKEN SHIM var w = [].indexOf || function(v){ for(i=this.length;i--&&this[i]!==v;);return i}, i, k, v; function c(){ k = []; v = []; } function h(o) { return -1 < (i = w.call(k, o)); } return { clear: c() || c, 'delete': function(o){ return !(h(o) ? (k.splice(i, 1), v.splice(i, 1), 0) : 1); }, get: function(o){ return v[w.call(k, o)]; }, has: h, set: function(o, d){ v[h(o) ? i : k.push(o) - 1] = d; } }; };
再看一下它的替代品MutationObserver,发现这厮不支持这功能,它只能监听自身或其后代的变化。因此还是用CSS方法或animationstart,IE6-9只能setInterval了!