MutationObserver で DOM 変更を監視する

Google 翻訳の Chrome 拡張機能がどうやって動いているのかなーとソースを追っていたら、MutationObserver なる API を発見した。

どうもコレで DOM の変更を監視できるようだ。

早速試してみた。以下の CodePen にアクセスしたら開発者ツールを表示し、「Append」ボタンや「Remove」ボタンを押してみよう。「PROCESS」というコンソール出力が確認できるはずだ。

// DOM 変更を検知した時に実行したい関数を定義しておく
const myCallbackFunc = (mutations) => {
  console.log('DOM 変更があった', mutations);
};

// コールバック関数を指定してインスタンスを作る
const observer = new MutationObserver(myCallbackFunc);

// body 要素配下の DOM 変更の監視を開始する
observer.observe(document.body, {
  childList    : true,  // 対象ノードの子ノード(テキストノードも含む)に対する追加・削除を監視する
  attributes   : true,  // 対象ノードの属性に対する変更を監視する
  characterData: true,  // 対象ノードのデータに対する変更を監視する
  subtree      : true   // 対象ノードとその子孫ノードに対する変更を監視する
});

// 監視を停止する場合は以下を呼ぶ
observer.disconnect();

new MutationObserver() のコンストラクタ引数に、コールバック関数を渡す。仮引数 mutations が受け取れる。

mutationObserver.observe() で監視を開始する際、監視したい親要素を指定できる。今回は document.bodybody 配下全体を監視したが、任意の Element を指定できる。

第2引数で色々とオプションを渡しているが、子要素を監視するか否か、とか、属性の変更も見るかどうか、とかが指定できる。今回はあらゆる変更を検知するようオプションを指定しておいた。

あとは body 要素の配下で、appendChild() だったり、innerHTML の書き換えだったりが発生すると、この MutationObserver が反応してコールバック関数を実行してくれる、というワケ。

テキストボックス (input 要素) や、テキストボックスの入力は監視できなかったので注意。コチラは素直に addEventListener('input') を使うかな。

はて、そうすると DOM 要素の変更を監視して何がしたいか、というと、あんまり使用頻度は多くない気がする。何に使おうか、考えてみる。