プログラミング

【PR】を含みます。

【JavaScript】Mutation ObserverでDOMの変化を監視する方法

JavaScript DOMの変化を監視する方法

JavaScriptのMutation ObserverでDOMの変化を監視する方法を紹介します。

Ajax通信で追加された要素に対して処理を実行、特定のclassが付与されたら処理を実行するなど、実務で時々使用するためコピペで使用できるようにまとめました。

Mutation Observerのオプション一覧

オプション
説明
childList
対象ノードの子ノードの追加と削除を監視します。
値:trueまたはfalse
attributes
対象ノードの属性の変更を監視します。
値:trueまたはfalse
characterData
対象ノードのテキストの変更を監視します。
値:trueまたはfalse
subtree
対象ノードおよびその子孫ノードの変化を監視します。
値:trueまたはfalse
attributeFilter
特定の属性の変更のみを監視します。
値:監視する属性名の配列
attributeOldValue
属性の変更前の値を記録します。
attributestrueの場合にのみ使用されます。
値:trueまたはfalse
characterDataOldValue
テキストの変更前の値を記録します。
characterDatatrueの場合にのみ使用されます。
値:trueまたはfalse

必須オプションについて

MutationObserverを正しく動作させるためには、以下のいずれか1つのオプションを指定する必要があります。

  • childList

  • attributes

  • characterData

【実装・テンプレートコード】Mutation ObserverでDOMの変化を監視

以下のコードはテンプレートのため複数のオプションを設定していますが、実務で使用する場合は必要なオプションのみを設定して使用することが多いです。

JavaSctipt
Copy
  1. // 監視対象の要素を取得
  2. const targetNode = document.querySelector('.watchElement');
  3.  
  4. // オプション設定
  5. const config = {
  6.   childList: true,
  7.   attributes: true,
  8.   characterData: true,
  9.   subtree: true,
  10.   attributeFilter: ['class', 'style', 'data-demo'],
  11.   attributeOldValue: true,
  12.   characterDataOldValue: true,
  13. };
  14.  
  15. // 変更が発生したときに呼び出されるコールバック関数
  16. const callback = function(mutationsList, observer) {
  17.   for (let mutation of mutationsList) {
  18.     // 変更があった箇所(要素)を取得
  19.     let targetElement = mutation.target;
  20.  
  21.     if (mutation.type === 'childList') {
  22.       // 子ノードに追加または削除があった場合の処理
  23.       console.log(`子ノードが追加または削除されました。変更箇所:`, targetElement);
  24.     } else if (mutation.type === 'attributes') {
  25.       // 属性に変更があった場合の処理
  26.       console.log(`${mutation.attributeName} 属性が変更されました。変更箇所:`, targetElement, `古い値: ${mutation.oldValue}`);
  27.     } else if (mutation.type === 'characterData') {
  28.       // テキストが変更された場合の処理
  29.       console.log(`テキストが変更されました。変更箇所:`, targetElement, `古い値: ${mutation.oldValue}`);
  30.     }
  31.   }
  32. };
  33.  
  34. // MutationObserverのインスタンスを作成
  35. const observer = new MutationObserver(callback);
  36.  
  37. // 監視対象の要素にMutationObserverを設定
  38. observer.observe(targetNode, config);

【サンプル】Mutation ObserverでDOMの変化を監視

「クリック」ボタンを押下すると、上記実装コードで実装しているconsole.log()の内容をディベロッパツールのコンソールで確認できます。

監視対象要素

サンプルで使用しているコード

JavaSctipt
Copy
  1. <div class="watchElement">監視対象要素</div>
  2. <button id="btn">クリック</button>
JavaSctipt
Copy
  1. // 監視対象の要素を取得
  2. const targetNode = document.querySelector('.watchElement');
  3.  
  4. // オプション設定
  5. const config = {
  6.   childList: true,
  7.   attributes: true,
  8.   characterData: true,
  9.   subtree: true,
  10.   attributeFilter: ['class', 'style', 'data-demo'],
  11.   attributeOldValue: true,
  12.   characterDataOldValue: true,
  13. };
  14.  
  15. // 変更が発生したときに呼び出されるコールバック関数
  16. const callback = function(mutationsList, observer) {
  17.   for (let mutation of mutationsList) {
  18.     // 変更があった箇所(要素)を取得
  19.     let targetElement = mutation.target;
  20.  
  21.     if (mutation.type === 'childList') {
  22.       // 子ノードに追加または削除があった場合の処理
  23.       console.log(`子ノードが追加または削除されました。変更箇所:`, targetElement);
  24.     } else if (mutation.type === 'attributes') {
  25.       // 属性に変更があった場合の処理
  26.       console.log(`${mutation.attributeName} 属性が変更されました。変更箇所:`, targetElement, `古い値: ${mutation.oldValue}`);
  27.     } else if (mutation.type === 'characterData') {
  28.       // テキストが変更された場合の処理
  29.       console.log(`テキストが変更されました。変更箇所:`, targetElement, `古い値: ${mutation.oldValue}`);
  30.     }
  31.   }
  32. };
  33.  
  34. // MutationObserverのインスタンスを作成
  35. const observer = new MutationObserver(callback);
  36.  
  37. // 監視対象の要素にMutationObserverを設定
  38. observer.observe(targetNode, config);
  39.  
  40. const btn = document.getElementById('btn');
  41.  
  42. btn.addEventListener('click', function () {
  43.   // 要素の追加
  44.   let createElement = document.createElement('div');
  45.   createElement.textContent = '要素を追加';
  46.   targetNode.appendChild(createElement);
  47.  
  48.   // 属性の変更
  49.   targetNode.classList.add('demo');
  50.   targetNode.setAttribute('data-demo', 'demo');
  51.  
  52.   // テキストの変更
  53.   targetNode.firstChild.data = '新しいテキスト';
  54. }, {once: true});

【実装コード】子ノードの追加と削除を監視

JavaSctipt
Copy
  1. // 監視対象の要素を取得
  2. const targetNode = document.querySelector('.watchElement');
  3.  
  4. // オプション設定
  5. const config = {
  6.   childList: true,
  7. };
  8.  
  9. // 変更が発生したときに呼び出されるコールバック関数
  10. const callback = function(mutationsList, observer) {
  11.   for (let mutation of mutationsList) {
  12.     if (mutation.type === 'childList') {
  13.       // 子ノードに追加または削除があった場合の処理
  14.       console.log('子ノードが追加または削除されました。');
  15.     }
  16.   }
  17. };
  18.  
  19. // MutationObserverのインスタンスを作成
  20. const observer = new MutationObserver(callback);
  21.  
  22. // 監視対象の要素にMutationObserverを設定
  23. observer.observe(targetNode, config);

【実装コード】属性の変更を監視

class等の属性の変更を監視することができます。

JavaSctipt
Copy
  1. // 監視対象の要素を取得
  2. const targetNode = document.querySelector('.watchElement');
  3.  
  4. // オプション設定
  5. const config = {
  6.   attributes: true,
  7. };
  8.  
  9. // 変更が発生したときに呼び出されるコールバック関数
  10. const callback = function(mutationsList, observer) {
  11.   for (let mutation of mutationsList) {
  12.     if (mutation.type === 'attributes') {
  13.       // 属性に変更があった場合の処理
  14.       console.log('属性が変更されました。');
  15.     }
  16.   }
  17. };
  18.  
  19. // MutationObserverのインスタンスを作成
  20. const observer = new MutationObserver(callback);
  21.  
  22. // 監視対象の要素にMutationObserverを設定
  23. observer.observe(targetNode, config);

【実装コード】テキストの変更を監視

JavaSctipt
Copy
  1. // 監視対象の要素を取得
  2. const targetNode = document.querySelector('.watchElement');
  3.  
  4. // オプション設定
  5. const config = {
  6.   characterData: true,
  7.   subtree: true,
  8. };
  9.  
  10. // 変更が発生したときに呼び出されるコールバック関数
  11. const callback = function(mutationsList, observer) {
  12.   for (let mutation of mutationsList) {
  13.     if (mutation.type === 'characterData') {
  14.       // テキストが変更された場合の処理
  15.       console.log('テキストが変更されました。');
  16.     }
  17.   }
  18. };
  19.  
  20. // MutationObserverのインスタンスを作成
  21. const observer = new MutationObserver(callback);
  22.  
  23. // 監視対象の要素にMutationObserverを設定
  24. observer.observe(targetNode, config);

テキストの変更を監視する場合の注意点

対象ノードのテキストの変更をcharacterDataとして検知したい場合、オプションにsubtree: trueを指定します。

テキストの変更は、dataプロパティを使用してテキストノードを直接変更する必要があります。

例:targetNode.firstChild.data = '新しいテキスト';

textContent等でテキスト変更が行われている場合、characterDataで検知することはできません。

textContentでテキストが変更されている場合、childListを使用して監視する必要があります。

【実装コード】Mutation Observerの監視を停止する方法

disconnect()メソッドを呼び出すことで、Mutation Observerの監視を停止できます。

以下のコードは、子ノードに追加または削除があった場合に監視を停止します。

JavaSctipt
Copy
  1. // 監視対象の要素を取得
  2. const targetNode = document.querySelector('.watchElement');
  3.  
  4. // オプション設定
  5. const config = {
  6.   childList: true,
  7. };
  8.  
  9. // 変更が発生したときに呼び出されるコールバック関数
  10. const callback = function(mutationsList, observer) {
  11.   for (let mutation of mutationsList) {
  12.     if (mutation.type === 'childList') {
  13.       // 子ノードに追加または削除があった場合の処理
  14.       console.log('子ノードが追加または削除されました。');
  15.       observer.disconnect(); // 監視を停止
  16.       break; // ループを抜ける
  17.     }
  18.   }
  19. };
  20.  
  21. // MutationObserverのインスタンスを作成
  22. const observer = new MutationObserver(callback);
  23.  
  24. // 監視対象の要素にMutationObserverを設定
  25. observer.observe(targetNode, config);

HTMLとCSSの知識がありJavaScriptを学びたいという方におすすめの1冊

アイコン画像

もみじ

HTMLとCSSの知識がありJavaScriptを学びたいという方に入門書としておすすめの書籍です。

実務で役立つサンプルを手を動かしながら学ぶことができ、実践的なスキルを身に付けることができます。

JavaScriptのフロントエンドエンジニアを目指している方におすすめの1冊

アイコン画像

もみじ

この本はJavaScript初心者からフロントエンドエンジニアを目指す方にぴったりの1冊です。

非同期処理やAJAXなど、現代の開発で必要なスキルがわかりやすく解説されており、実務で役立つスキルを学ぶことができます。

-プログラミング
-