もくじ
JavaScriptのMutation ObserverでDOMの変化を監視する方法を紹介します。
Ajax通信で追加された要素に対して処理を実行、特定のclassが付与されたら処理を実行するなど、実務で時々使用するためコピペで使用できるようにまとめました。
Mutation Observerのオプション一覧
- オプション
- 説明
- childList
- 対象ノードの子ノードの追加と削除を監視します。
値:true
またはfalse
- attributes
- 対象ノードの属性の変更を監視します。
値:true
またはfalse
- characterData
- 対象ノードのテキストの変更を監視します。
値:true
またはfalse
- subtree
- 対象ノードおよびその子孫ノードの変化を監視します。
値:true
またはfalse
- attributeFilter
- 特定の属性の変更のみを監視します。
値:監視する属性名の配列
- attributeOldValue
- 属性の変更前の値を記録します。
attributes
がtrue
の場合にのみ使用されます。
値:true
またはfalse
- characterDataOldValue
- テキストの変更前の値を記録します。
characterData
がtrue
の場合にのみ使用されます。
値:true
またはfalse
必須オプションについて
MutationObserverを正しく動作させるためには、以下のいずれか1つのオプションを指定する必要があります。
childList
attributes
characterData
【実装・テンプレートコード】Mutation ObserverでDOMの変化を監視
以下のコードはテンプレートのため複数のオプションを設定していますが、実務で使用する場合は必要なオプションのみを設定して使用することが多いです。
// 監視対象の要素を取得
const targetNode = document.querySelector('.watchElement');
// オプション設定
const config = {
childList: true,
attributes: true,
characterData: true,
subtree: true,
attributeFilter: ['class', 'style', 'data-demo'],
attributeOldValue: true,
characterDataOldValue: true,
};
// 変更が発生したときに呼び出されるコールバック関数
const callback = function(mutationsList, observer) {
for (let mutation of mutationsList) {
// 変更があった箇所(要素)を取得
let targetElement = mutation.target;
if (mutation.type === 'childList') {
// 子ノードに追加または削除があった場合の処理
console.log(`子ノードが追加または削除されました。変更箇所:`, targetElement);
} else if (mutation.type === 'attributes') {
// 属性に変更があった場合の処理
console.log(`${mutation.attributeName} 属性が変更されました。変更箇所:`, targetElement, `古い値: ${mutation.oldValue}`);
} else if (mutation.type === 'characterData') {
// テキストが変更された場合の処理
console.log(`テキストが変更されました。変更箇所:`, targetElement, `古い値: ${mutation.oldValue}`);
}
}
};
// MutationObserverのインスタンスを作成
const observer = new MutationObserver(callback);
// 監視対象の要素にMutationObserverを設定
observer.observe(targetNode, config);
【サンプル】Mutation ObserverでDOMの変化を監視
「クリック」ボタンを押下すると、上記実装コードで実装しているconsole.log()
の内容をディベロッパツールのコンソールで確認できます。
サンプルで使用しているコード
<div class="watchElement">監視対象要素</div>
<button id="btn">クリック</button>
// 監視対象の要素を取得
const targetNode = document.querySelector('.watchElement');
// オプション設定
const config = {
childList: true,
attributes: true,
characterData: true,
subtree: true,
attributeFilter: ['class', 'style', 'data-demo'],
attributeOldValue: true,
characterDataOldValue: true,
};
// 変更が発生したときに呼び出されるコールバック関数
const callback = function(mutationsList, observer) {
for (let mutation of mutationsList) {
// 変更があった箇所(要素)を取得
let targetElement = mutation.target;
if (mutation.type === 'childList') {
// 子ノードに追加または削除があった場合の処理
console.log(`子ノードが追加または削除されました。変更箇所:`, targetElement);
} else if (mutation.type === 'attributes') {
// 属性に変更があった場合の処理
console.log(`${mutation.attributeName} 属性が変更されました。変更箇所:`, targetElement, `古い値: ${mutation.oldValue}`);
} else if (mutation.type === 'characterData') {
// テキストが変更された場合の処理
console.log(`テキストが変更されました。変更箇所:`, targetElement, `古い値: ${mutation.oldValue}`);
}
}
};
// MutationObserverのインスタンスを作成
const observer = new MutationObserver(callback);
// 監視対象の要素にMutationObserverを設定
observer.observe(targetNode, config);
const btn = document.getElementById('btn');
btn.addEventListener('click', function () {
// 要素の追加
let createElement = document.createElement('div');
createElement.textContent = '要素を追加';
targetNode.appendChild(createElement);
// 属性の変更
targetNode.classList.add('demo');
targetNode.setAttribute('data-demo', 'demo');
// テキストの変更
targetNode.firstChild.data = '新しいテキスト';
}, {once: true});
【実装コード】子ノードの追加と削除を監視
// 監視対象の要素を取得
const targetNode = document.querySelector('.watchElement');
// オプション設定
const config = {
childList: true,
};
// 変更が発生したときに呼び出されるコールバック関数
const callback = function(mutationsList, observer) {
for (let mutation of mutationsList) {
if (mutation.type === 'childList') {
// 子ノードに追加または削除があった場合の処理
console.log('子ノードが追加または削除されました。');
}
}
};
// MutationObserverのインスタンスを作成
const observer = new MutationObserver(callback);
// 監視対象の要素にMutationObserverを設定
observer.observe(targetNode, config);
【実装コード】属性の変更を監視
class
等の属性の変更を監視することができます。
// 監視対象の要素を取得
const targetNode = document.querySelector('.watchElement');
// オプション設定
const config = {
attributes: true,
};
// 変更が発生したときに呼び出されるコールバック関数
const callback = function(mutationsList, observer) {
for (let mutation of mutationsList) {
if (mutation.type === 'attributes') {
// 属性に変更があった場合の処理
console.log('属性が変更されました。');
}
}
};
// MutationObserverのインスタンスを作成
const observer = new MutationObserver(callback);
// 監視対象の要素にMutationObserverを設定
observer.observe(targetNode, config);
【実装コード】テキストの変更を監視
// 監視対象の要素を取得
const targetNode = document.querySelector('.watchElement');
// オプション設定
const config = {
characterData: true,
subtree: true,
};
// 変更が発生したときに呼び出されるコールバック関数
const callback = function(mutationsList, observer) {
for (let mutation of mutationsList) {
if (mutation.type === 'characterData') {
// テキストが変更された場合の処理
console.log('テキストが変更されました。');
}
}
};
// MutationObserverのインスタンスを作成
const observer = new MutationObserver(callback);
// 監視対象の要素にMutationObserverを設定
observer.observe(targetNode, config);
テキストの変更を監視する場合の注意点
対象ノードのテキストの変更をcharacterData
として検知したい場合、オプションにsubtree: true
を指定します。
テキストの変更は、data
プロパティを使用してテキストノードを直接変更する必要があります。
例:targetNode.firstChild.data = '新しいテキスト';
textContent
等でテキスト変更が行われている場合、characterData
で検知することはできません。
textContent
でテキストが変更されている場合、childList
を使用して監視する必要があります。
【実装コード】Mutation Observerの監視を停止する方法
disconnect()
メソッドを呼び出すことで、Mutation Observerの監視を停止できます。
以下のコードは、子ノードに追加または削除があった場合に監視を停止します。
// 監視対象の要素を取得
const targetNode = document.querySelector('.watchElement');
// オプション設定
const config = {
childList: true,
};
// 変更が発生したときに呼び出されるコールバック関数
const callback = function(mutationsList, observer) {
for (let mutation of mutationsList) {
if (mutation.type === 'childList') {
// 子ノードに追加または削除があった場合の処理
console.log('子ノードが追加または削除されました。');
observer.disconnect(); // 監視を停止
break; // ループを抜ける
}
}
};
// MutationObserverのインスタンスを作成
const observer = new MutationObserver(callback);
// 監視対象の要素にMutationObserverを設定
observer.observe(targetNode, config);
HTMLとCSSの知識がありJavaScriptを学びたいという方におすすめの1冊
JavaScriptのフロントエンドエンジニアを目指している方におすすめの1冊
もみじ
この本はJavaScript初心者からフロントエンドエンジニアを目指す方にぴったりの1冊です。
非同期処理やAJAXなど、現代の開発で必要なスキルがわかりやすく解説されており、実務で役立つスキルを学ぶことができます。
もみじ
HTMLとCSSの知識がありJavaScriptを学びたいという方に入門書としておすすめの書籍です。
実務で役立つサンプルを手を動かしながら学ぶことができ、実践的なスキルを身に付けることができます。