このブログのはてなブックマーク数 このエントリーをはてなブックマークに追加

知らなきゃ絶対損するPCマル秘ワザ

知らなくて損したPC情報とかを分かりやすくメモする個人ブログ。
『月,水,金』の週3回更新!(予定)

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

このエントリーをはてなブックマークに追加
操作画面


こんにちは、さち です。

先日、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」で動かない時に有効にするという理解で何とかなる)

監視する「もの」の指定では、下記の項目も併用できます。
「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 のブラウザ対応状況は
IE が11以降、Edge がすべて、Firefox が14以降、Chrome が18以降、Safari が6以降、
iOS が6.1以降、Android が 4.4以降です。
よほど古いブラウザでない限りほぼ大丈夫ですね。




このエントリーをはてなブックマークに追加




ブログ移転に伴い、コメント受付は終了しました。



記事別の週間アクセス数ランキングです。こちらの記事もぜひ読んでみて下さい。

2008-2019 知らなきゃ絶対損するPCマル秘ワザ  無断転載禁止

ブログパーツ