DOMNodeInserted 和 DOMNodeRemoved 事件
在DOM中可以通過(guò)DOMNodeInserted和DOMNodeRemoved這兩個(gè)事件來(lái)監(jiān)視DOM元素的插入和移除。但由于各瀏覽器中DOM樹(shù)的處理方式不同,導(dǎo)致了這兩個(gè)事件在各個(gè)瀏覽器上都有各自的特點(diǎn)。只要知道了這些特定,使用時(shí)做特殊處理就能暫時(shí)解決問(wèn)題。
以下測(cè)試是在文檔對(duì)象上綁定這兩個(gè)事件(它們是會(huì)冒泡的),并通執(zhí)行一系列DOM樹(shù)的操作:
<script>
addEventListener("DOMContentLoaded",function(){
document.addEventListener("DOMNodeInserted",function(e) {
console.log("insert",e.target);
});
document.addEventListener("DOMNodeRemoved",function(e) {
console.log("remove",e.target);
});
var div=document.createElement("div");
div.innerHTML="<span>span</span>";
console.log("%cinnerHTML","color:red");
document.body.innerHTML="<div><span>span</span></div>text";
console.log("%cinsertAdjacentHTML","color:red");
document.body.insertAdjacentHTML("beforeend","<div>div</div>");
console.log("%cappendChild","color:red");
document.body.appendChild(div);
document.body.appendChild(div); //重復(fù)調(diào)用 appendChild
console.log("%cremoveChild","color:blue");
document.body.removeChild(div);
console.log("%cinnerHTML","color:blue");
document.body.innerHTML="";
});
</script>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23

Firefox比Chrome的結(jié)果長(zhǎng)了許多,首先在 insertAdjacentHTML 時(shí)它把已存在的元素都觸發(fā)了一次 DOMNodeInserted 但,這些元素并沒(méi)有觸發(fā) DOMNodeRemoved ,我覺(jué)得此處為Firefox的BUG。另外對(duì)于已經(jīng)存在了的元素執(zhí)行 appendChild ,即使位置相同F(xiàn)irefox也會(huì)先移除這個(gè)元素在插入這個(gè)元素,所以 DOMNodeInserted 和 DOMNodeRemoved 事件都會(huì)被觸發(fā),而Chrome上優(yōu)化掉了這個(gè)操作,所以事件沒(méi)有觸發(fā)(我覺(jué)得這方面Firefox的行為比較正確)。

接下來(lái)是IE上的執(zhí)行結(jié)果,這里使用了IE11上的IE9模式測(cè)試:
由于IE不支持控制臺(tái)的“%c”命令,所以輸出結(jié)果有點(diǎn)難看,不過(guò)還是能看懂的。IE對(duì) insertAdjacentHTML 的處理同Chrome,對(duì) appendChild 的處理同F(xiàn)irefox,這些處理我很贊同。但是IE會(huì)對(duì)插入元素的后代節(jié)點(diǎn)都觸發(fā)一次 DOMNodeInserted ,我覺(jué)得這是不對(duì)的,或者說(shuō)是IE的BUG吧。
總之這兩個(gè)事件在Chrome、Firefox、IE上都有各自的問(wèn)題,使用時(shí)需要做一些特殊判斷來(lái)處理。最后也希望瀏覽器本身能早日統(tǒng)一這些東西吧。
|