【JavaScript】MutationObserver で DOM を省エネ監視

 MutationObserver は DOM を監視する JavaScript 組み込み機能です。
MutationObserver – Web API | MDN
 MutationObserver では click, input 等のイベントではカバーしきれない待ち受けができます。例えば次のデモの様に innerText の変化を監視できます。

// オブザーバインスタンスを作成
// @see https://developer.mozilla.org/ja/docs/Web/API/MutationObserver
const observer = new MutationObserver((mutations) => {
  // mutations にはこのインスタンスで待ち受けているもの全てが配列で入ってきます
  // この配列は MutationRecord インスタンスの配列です
  // https://developer.mozilla.org/ja/docs/Web/API/MutationRecord
  console.log(mutations);
  document.querySelector('#observe-result').textContent = JSON.stringify({
  '変化前の値': (mutations[0].removedNodes[0]) && mutations[0].removedNodes[0].textContent,
  '変化後の値': (mutations[0].addedNodes[0]) && mutations[0].addedNodes[0].textContent
  },null,2)
});

/**
 * 監視設定。以下の項目で必要なだけの監視をできます。
 * childList             対象ノードの子ノード(テキストノードも含む)に対する追加・削除を監視する場合は true にします。
 * attributes            対象ノードの属性に対する変更を監視する場合は true にします。
 * characterData         対象ノードのデータに対する変更を監視する場合は true にします。
 * subtree               対象ノードとその子孫ノードに対する変更を監視する場合は true にします。
 * attributeOldValue     対象ノードの変更前の属性値を記録する場合は true にします(attributes が true の時に有効)。
 * characterDataOldValue 対象ノードの変更前のデータを記録する場合は true にします(characterData が true の時に有効)。
 * attributeFilter       すべての属性の変更を監視する必要がない場合は、(名前空間を除いた)属性ローカル名の配列を指定します。
 * @type {MutationObserverInit}
 */
const config = {
  childList: true,
  attributes: true,
  characterData: true,
  subtree: true,
  attributeOldValue: true,
  characterDataOldValue: true
}

// 監視対象のElementと監視設定をオブザーバインスタンスに渡して、監視が始まります
observer.observe(document.getElementById('observe-target'), config);


// 以下デモ用
// 入力されたら監視対象ノードの text ノードを書き換え
document.getElementById('input').addEventListener(
  'input',
  (e) => {
    const val = e.target.value;
    document.getElementById('observe-target').innerText
        = Array.from(val).map(c => slideChar(c)).join('')
  }
)

/** 与えられた文字をずらす関数 */
function slideChar(chars, slideWidth = 1) {
  if (chars[0] === 'z') {
    return 'a';
  }
  return String.fromCharCode(chars.charCodeAt(0) + slideWidth)
}

 私的にこれが役に立つのは素の JavaScript を前提とした複数のライブラリ間の協調です。それぞれのライブラリが独自のライフサイクルで動いている(そもそもライフサイクルの概念がなかったり)中では、準備し終わっていない機能を無理やり動かそうとして致命的エラーになる、といった事態も起きます。
 DOM を監視して適切なタイミングで処理を走らせることによって、そういったエラーを防げます、

>株式会社シーポイントラボ

株式会社シーポイントラボ

TEL:053-543-9889
営業時間:9:00~18:00(月〜金)
住所:〒432-8003
   静岡県浜松市中央区和地山3-1-7
   浜松イノベーションキューブ 315
※ご来社の際はインターホンで「316」をお呼びください

CTR IMG