こんにちは、さち です。
先日、JavaScript を書いていたんですが、要素 <div>
の中身が変化した時にイベントを起こしたいことがありました。
最初は、addEventListener
の change
を使ったんですがダメでした。要素の中身の変化を検出するには、MutasionObserver
を使わないといけないみたいです。
「change」イベントでは動かない
<div>
の中身が変更されたらアラート(ダイアログ)を出すように、<div>
に addEventListener
の change
を設定して、こんな 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);
しかし、下記のサンプルのとおりアラートは出ません。
addEventListener
の change
は、基本的に <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 以降 |
よほど古いブラウザでない限りほぼ大丈夫ですね。
コメント