JavaScript:要素の中身が変化した時にイベントを起こしたい

この記事は約5分で読めます。
記事内に広告が含まれています

操作画面

こんにちは、さち です。

先日、JavaScript を書いていたんですが、要素 <div> の中身が変化した時にイベントを起こしたいことがありました。

最初は、addEventListenerchange を使ったんですがダメでした。要素の中身の変化を検出するには、MutasionObserver を使わないといけないみたいです。

スポンサーリンク

「change」イベントでは動かない

<div> の中身が変更されたらアラート(ダイアログ)を出すように、<div>addEventListenerchange を設定して、こんな HTML, JavaScript を書きました。

<div>にー</div>
<button>「にっこ」追加</button>
var div = document.getElementsByTagName('div')[0];
div.addEventListener('change', function() {
  alert('divの中身が変更されたよ');
}, false);

var button = document.getElementsByTagName('button')[0];
button.addEventListener('click', function() {
  div.textContent = 'にっこ' + div.textContent;
}, false);

しかし、下記のサンプルのとおりアラートは出ません。

サンプル

addEventListenerchange は、基本的に <input><select> の変化しか検出しないので、<div> の中身が変化しても何も起こらないのです。

「MutationObserver」を使う

MutationObserver を使うことで、<div> などの要素の中身の変更も検出できます。

Mutation(ミューテーション) は「変化」、Observer(オブザーバー)は「監視者」という意味なので、まさにそのままの名前です。

今回の例で使うとこんな感じ。

var div = document.getElementsByTagName('div')[0];
var mo = new MutationObserver(function() {
  alert('divの中身が変更されたよ');
});
var config = {
  childList: true
};
mo.observe(div, config);

var button = document.getElementsByTagName('button')[0];
button.addEventListener('click', function() {
  div.textContent = 'にっこ' + div.textContent;
}, false);

実際のサンプルがこちら。ちゃんとアラートが出ます。

サンプル

「MutationObserver」の使い方

MutationObserver を使う際の流れはこんな感じ。

//監視する要素の指定
var element = document.getElementById('id');

//MutationObserver(インスタンス)の作成
var mo = new MutationObserver(function(record, observer) {
  /* 変更検出時に実行する内容 */
});

//監視する「もの」の指定(必ず1つ以上trueにする)
var config = {
  childList: true,//「子ノード(テキストノードも含む)」の変化
  attributes: true,//「属性」の変化
  characterData: true,//「テキストノード」の変化
};

//監視の開始
mo.observe(element, config);

//監視の終了
mo.disconnect();

MutationObserver はインスタンスを作っただけでは機能しません。observe メソッドで監視を開始しましょう。

監視するものは、次の3つの中から必ず1つ以上有効(true)にします。

childList 子ノード(中身)の変化を検出
attributes 属性名,属性値の変化を検出
characterData テキストノードの変化を検出(「childList」が動かない時に有効にする認識でOK)

監視する「もの」の指定では、下記の項目も併用できます。attributeOldValue characterDataOldValue を有効にした場合、変更前の値は MutationObserver の引数 record に配列として記録されます。

var config = {
  childList: true,
  attributes: true,
  characterData: true,
  subtree: true,//孫以降のノードの変化も検出
  attributeOldValue: true,//変化前の属性データを記録する
  characterDataOldValue: true,//変化前のテキストノードを記録する
  attributeFilter: [],//配列で記述した属性だけを見張る
});

subtree: true は使う機会が多そうなので実験してみます。

どちらの <div> にも MutationObserver を設定し、childList: true としていますが、subtree の設定が異なっています。<div> 内にある <span> の中身を変える場合、subtree: true でないと反応しません。

サンプル

ウェブブラウザーの対応

Can I use... によると、MutationObserver に対応している各ウェブブラウザーのバージョンは次のとおりです。

Chrome 18 以降
Firefox 14 以降
Edge すべて
Internet Explorer 11 以降
Safari 6 以降
iOS 6.1 以降
Android 4.4 以降

よほど古いブラウザでない限りほぼ大丈夫ですね。

コメント

タイトルとURLをコピーしました