JavaScriptで要素の追加・削除やテキストの変更を監視する方法

要素の属性値が変わったとき、要素が追加・削除されたとき、要素の中身が変更されたとき・・・

このような場合に変更を感知して何かイベント処理したいこともありますよね?

ただ標準のイベントではそれを感知する術はありません。

では諦めるしかないのか、というとそうではなく解決策はあります。

ここでは要素(DOM)の変化の監視方法について紹介します。

要素の変化の感知にchangeは使えない・・・

まず初めに注意しておきたいこと

それは要素の中身の変化、要素の追加や削除の感知にchangeイベントは使えないということです。

 

例えば次のようにjQueryでdiv要素の中身の変化を  change  で監視しようとしても無駄です。

上のようなコードは何もしていないのと同じです。

 

なぜならchangeイベントというのは入力欄のvalue属性の値が変化したときだけに発生するからです。

入力欄というのは例えばテキストエリアとかチェックボックスとか選択肢のこと

それに当てはまらないdiv要素などではそもそもchangeイベントは起こりません。

 

ではどうすれば要素の変化を監視できるのか・・・

その正しい答えは MutationObserver というJavaScriptのAPIを使うことです。

MutationObserverとは何か?その特長

MutationObserver要素(DOM)の変化時に指定したコールバック関数を実行できるAPIです。

先ほど書いたようにこれはjQueryの機能ではなく、JavaScriptで用意されたAPIとなっています。

 

ではこのMutationObserverで要素の変化の何が監視できるかというと主に次のようなこと

  • 属性値・CSSプロパティの変化
  • 要素の追加・削除
  • 要素内のテキストの変更
  • その他色々・・・

つまり今まで監視できなかった要素の色々な変化をイベントとして受け取ることができるってことです。

 

MutationObserverの各ブラウザの対応状況については Can I use... の次のページから確認可能

Opera Mini以外はすべてのブラウザで対応済みなので実用的に使えます。

MutationObserverでDOM変化を監視する方法

ではこれを使って要素を監視する手順を大まかに書くと次のような感じ

  • MutationObserverを作ってコールバック関数登録
  • observeメソッドに監視したい要素とオプションを渡す

これだけだと分かりにくいの次で例を使って説明していきます。

 

まず次のようにMutationObserverインスタンスを作成

インスタンスを作るときにコールバック関数が渡せ、DOM変化が起こった時にそれが実行されます。

今回はノード変化があるたびにコンソールにメッセージを出力してみます。

 

そうしたら次は変化を監視したい要素getElementById で取得

上の例のように  'my_example'  などのIDを指定して要素オブジェクトを取得すればOKです。

 

では次にDOM監視時のオプションを作成しましょう。

この例のように連想配列形式で1つ以上のプロパティを持つオプションを作ってください。

オプション内で指定できる各プロパティとその意味についてはそれぞれ次の通り

プロパティ 取れる値 意味
childList true または false 子ノードの変化も監視するかどうか
attributes true または false ノードの属性変化を監視するかどうか
characterData true または false ノードのデータ変化を監視するかどうか
subtree true または false 子孫ノードの変化も監視するかどうか
attributeOldValue true または false 変更前のノードの属性値を記録するかどうか
characterDataOldValue true または false 変更前のノードのデータを記録するかどうか
attributeFilter 属性ローカル名の配列

ノードの属性値やデータの変化を監視対象に含めるか、あるいは子ノードや子孫ノードも監視対象にするか、などの設定ができます。

 

では最後に先ほど作成したMutationObserverに対して次のようにobserveメソッドを実行しましょう。

これで指定した要素またはその子・孫要素内で属性変化やデータ変化があるたびにコールバック関数が呼ばれることになります。

 

ちなみにここまでの全体のコードは次の通り

この例だと要素の属性変化(attributes)、子ノードの変化(childList)、要素内テキストの変化(characterData)の3つの変化を監視しています。

 

以上がMutationObserverの使い方です。

ほとんどのブラウザで対応済みなので特に互換性なども気にする必要もありません。

まとめ

MutationObserverを使うと簡単に要素の変化が監視できます。

jQueryが使えないのが少し残念ですが、使い方もそれほど難しくないので便利です。

ということで要素の変化を受け取るのにMutationObseverを使おうよという話でした。

ではではヾ(・◇・)ノ