10
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

【JavaScript】Mutation ObserverでDOMを監視する

Last updated at Posted at 2023-06-05

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】要素の変化を検知して何かをするカスタムフックを作成する

参考文献

  1. MutationObserver の使い方
  2. Mutation observer
10
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
10
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?