MutationObserver/Mutation Events は孫DOMへの操作も検知するのか
MutationObserver/Mutation Events は、孫DOMへの操作も検知するのだろうか。Chrome48.0.2564.103 とFirefox44.0.2で検証した。
※ざっくりした調査なのでご参考までに。
結論
MutationObserverは仕様にsubtree
オプションがあり、ChromeもFirefoxもこれを実装している。問題なく検知する。
Mutation Events (廃止された仕様) は、Chromeで一部検知しない。Firefoxでは検知できた。
Mutation Events
廃止された仕様。使ってはいけない。Mutation events - Web developer guides | MDN
とりあえず、この3つだけを調査の対象とする。全イベント一覧はこちら
- DOMAttrModified
- DOMNodeInserted
- DOMNodeRemoved
HTML
<body> <div> <div id="descendant"></div> </div> <script src="./main.js"></script> </body>
JavaScript
'use strict'; /* * Mutation Events を document.body に登録する */ [ 'DOMAttrModified', 'DOMNodeInserted', 'DOMNodeRemoved' ] .forEach(type => { document.body.addEventListener(type, e => { console.log('=======', e.type); }); }); /* * 孫DOMに対し、操作を加えてみる */ test(); function test() { let el = document.getElementById('descendant'); let textNode = document.createTextNode('boooom'); el.setAttribute('boom', 'boom'); el.appendChild(textNode); setTimeout(() => el.removeChild(textNode), 800); }
実行結果
Firefox
全てのイベントがdocument.body
まで伝播している。
======= DOMAttrModified a.js:10:5 ======= DOMNodeInserted a.js:10:5 ======= DOMNodeRemoved a.js:10:5
Chrome
DOMAttrModifiedだけdocument.body
に来ない。
======= DOMNodeInserted a.js:10 ======= DOMNodeRemoved a.js:10
MutationObserver
MutationObserver - Web API インターフェイス | MDN
結果として、FirefoxもChromeも仕様通り機能した。平和平和。
JavaScript
HTMLと、検証用test()
関数は上記と同じ。MutationObserverのコードをこうした。
/* * Mutation Observerを登録。 */ let mo = new MutationObserver(mutationRecords => { console.log('=======', mutationRecords.map(r => r.type)); }); mo.observe(document.body, { childList: true, attributes: true, characterData: true, subtree: true, /* ここポイント */ attributeOldValue: true, characterDataOldValue: true });
Firefox
======= Array [ "attributes", "childList" ] a.js:19:3 ======= Array [ "childList", "characterData", "characterData" ] a.js:19:3 ======= Array [ "childList" ] a.js:19:3
Chrome
======= ["attributes", "childList"] a.js:19 ======= ["childList", "characterData", "characterData"] a.js:19 ======= ["childList"] a.js:19
同じ結果を返していることが分かる。
参考にした記事
非推奨になった Mutation events を Mutation Observers に置き換えよう - ログろいど