Mutation Observerとは
DOMの変化を監視することができるWeb APIである。
Mutation Observerの使い方
監視対象の要素を設定
まず、監視対象の要素を決めなければならない。
以下は idがsampleの要素を取得し、監視対象に設定している。
// idがsampleの要素を監視対象に設定
const targetNode = document.getElementById('sample');
全体DOMを監視対象とするには、以下のようにする。
// DOM全体を監視対象に設定
const targetNode = document.documentElement;
監視オプションの設定
以下のコードのようにオプションを設定する。以下の例では監視対象ノードとその子孫ノードの属性の変更や子要素の追加/削除、さらにはテキストノードの変更までを監視する。
// 監視オプションの設定
const config = { attributes: true, childList: true, subtree: true };
オプションの一覧
attributeFilter以外は全部bool値である。
オプション名 | 説明 |
---|---|
childList | 子要素の追加や削除の変更を監視するかどうか。 |
attributes | 属性の変更を監視するかどうか。 |
characterData | テキストノードの内容の変更を監視するかどうか。 |
subtree | 監視対象ノードの子孫ノード全体の変更を監視するかどうか。 |
attributeOldValue | attributesがtrueの場合、変更前の属性値を保持する。 |
characterDataOldValue | characterDataがtrueの場合、変更前のテキストノードの内容を保持する。 |
attributeFilter | 監視する特定の属性名の配列。この配列に含まれない属性の変更は無視される。 |
コールバック関数の設定
監視対象に変更が生じた際に実行されるコールバック関数を設定する。
// Mutation Observerのコールバック関数
const handleMutation = (mutationsList, observer) => {
mutationsList.forEach(mutation => {
// 変更に対する処理
console.log('DOMが変更されました:', mutation);
});
};
コールバック関数の第1引数(上記の場合はmutationsList)にはMutationRecordオブジェクトの配列が入っている。MutationRecordにはDOM変化の情報が入ってる。
監視を開始する
observerのインスタンスを作成し、observe() で監視を開始する。
// コールバック関数に結びつけられたオブザーバーのインスタンスを生成
const observer = new MutationObserver(handleMutation);
// 対象ノードの設定された変更の監視を開始
observer.observe(targetNode, options);
監視の終了
disconnect() で終了できる
observer.disconnect();
監視できないもの
監視対象のイベントハンドラーは監視することができない。
実際に使ってみた例
jQuery
jQueryで$(document).ready(function() {});
や$(window).on('load', function(){});
を使った場合だと、タイミングが合わないときがある。
たとえば、以下のように実装すると、$(window).on('load', function(){});
がsampleの要素が存在しないというエラーがでるときがある。
$(window).on('load', function(){
$('#sample').after('<p>hoge</p>')
});
ちなみに以下のように時間を空けると成功する。
$(window).on('load', function(){
setTimeout(function() {
$('#sample').after('<p>hoge</p>')
}, 1000);
});
しかし、この場合だと最適な時間を設定するのが難しい。
そこで Mutation Observer を用いる。
// 監視する範囲を指定(document.documentElementは全体のDOMを対象とする)
const targetNode = document.documentElement;
// オプションを設定
const config = { childList: true, subtree: true };
// Mutation Observerの作成
const observer = new MutationObserver(function (mutationsList, observer) {
for (let mutation of mutationsList) {
if (mutation.type === "childList" && mutation.addedNodes.length > 0) {
// 追加されたノードをチェック
for (let node of mutation.addedNodes) {
if ($(node).is("#sample")){
// 監視を終了する
observer.disconnect();
// 追加されたら必要な処理を実行
$('#sample').after('<p>hoge</p>')
}
}
}
}
});
// Mutation Observerを開始
observer.observe(targetNode, config);
React
Mutaion Observerを使用して、カスタムフックを作成する例があったので、参考に挙げておく。
【React hooks】要素の変化を検知して何かをするカスタムフックを作成する