- web design -

blog

MutationObserverで動的に追加した要素を取得したりごにょごにょしてみた

JavaScript

MutationObserver

 

 

こんにちは、ma-ya’s CREATE[まーやずくりえいと]です。

 

Javascriptで動的に追加した要素をさらに取得してごにょごにょしたい時、たまーにあると思います。

構築時よりはサイト運用でやりたい or やらざるを得ない場合が稀にあって、比較的新しいAPIがあったので使ってみました。

 

 

ターゲット要素を監視して、動的に要素が追加されたら何かをするMutationObserver

 

まずはサンプルをば。

 

See the Pen
Mutation Observer – experiment
by mycreatesite (@mycreatesite)
on CodePen.

 

サンプルは以下の流れで動きを見て下さい。

 

  1. (念のため)ブラウザのキャッシュをクリアする(スーパーリロード
  2. ボタンをクリックしてサイズが異常にでかい画像(img)要素を生成
  3. 画像が全て読み込まれるとブラウザにアラートが表示される

 

どうでしょう?

良い感じに動的に生成した要素の読み込みを待って(loadイベント後に)アラートが表示されるはずです。

 

 

[コード解説]意外とシンプルに使えるMutationObserver

 

サンプルのMutationObserverに関する記述はこんな感じ↓

 

コメントが全てと言えばすべてなんですが、ちょっと気を付けるところもあったのでポイントをかいつまんで解説していきます。

 

 

1. 監視する要素を決める

 

監視する要素を決めます。

 

この時注意なのは、監視する要素というのは動的に変更する要素のことではありません

監視する範囲となる外枠の要素、といった方がわかりやすいかもしれませんが、サンプルではbodyとしています。

 

 

2. MutationObserverインスタンスを生成

 

インスタンスを生成します。

インスタンスは引数に要素変更を検知した時のコールバック関数をとります。

 

 

3. 要素変更を検知した時に何かする処理(コールバック関数)

 

ここがちょっとややこしめかもしれないです。

とりあえずコールバック関数のみ抜粋したのがこちら。

 

function callback(mutations){ // mutations →(動的な)要素変更情報の集合体
  mutations.forEach( mutation => { // mutation → 個別の(動的な)要素変更情報
    mutation.addedNodes.forEach( node => { // mutation.addedNodes → 追加された要素(ノードリスト)
      if(node.tagName==='IMG') {
        node.addEventListener('load',()=>{
          alert('Image fully loaded !');
        });
      }
    });
  });
}

 

コールバック関数は引数に動的な要素変更情報をとる

 

mutations

 

コールバックは引数に様々な要素変更情報を含む配列をとります。

変更要素が複数ある場合はキーと値のオブジェクト形式でそれぞれ変更要素の数だけ情報が格納されます。

コンソールで見てみるとわかりやすいので見てみましょう。

 

 

MutationObserver01

 

mutation

 

変更情報を個別に処理するため、mutationsをforEachで回します。

個別のmutationをコンソールで見るとこんな感じ。

 

MutationObserver02

 

動的に追加した要素にイベントリスナを設定する

 

今回のサンプルでは、動的に追加したimg要素の読み込みが完了したらアラートを出すというイベントを、動的に追加されたimg要素に設定する必要があります。

その為今回は↑の画像の通りmutation.addedNodesにアクセスして、追加された要素リスト(node list)を取得→さらにループを回しています。

※この辺りイベントリスナを設定するのが単数の場合はループではなくブラケット[]でアクセスしてもいいと思います

 

サンプルではimg要素だけにイベントリスナを設定したかったので、ノードのtagNameプロパティにアクセス→条件分岐という流れでイベント設定しています。

 

 

4. MutationObserverの監視設定(何をどこまで監視するか?みたいなこと)

 

ここではMutationObserverがどのようにターゲット要素を監視するかを設定します。

対象要素の子要素や子孫要素も含めるのか?属性も監視するのか?などオプションを選べます。

 

オプション説明はMDNさんにお願いしましょう(丸投げ)

 

MutationObserver03

 

ちなみにオプションは、attributes、characterData、または childList の少なくとも1つをtrueに設定する必要があります。

 

 

5. MutationObserverインスタンスに監視要素とオプションを教えてあげる

 

MutationObserverさんにターゲット要素をオプションを教えてあげましょう。

 

と、コード説明はこんな感じです。

もし時間があったらコールバックの引数をコンソールで眺めてみると理解が深まったり、できること・できないことが見えてくるかもしれません。

 

 

MutationObserverのブラウザサポート状況

 

最後にブラウザのサポート状況です。

2020/7/6現在のサポート状況はこんな感じ↓

 

MutationObserver support

 

意外とIE11もサポートしてるんですよね笑

 

observer系のAPIは当然の如くIE死亡と思い込んでたので少し見直しました。

いや見直しはしないな。

 

早くIEは全部爆発して全滅してほしい。

 

 

[余談]MutationObserverは廃止されるのか?

 

なぜかGoogle検索で「MutationObserver」を検索すると予測変換で「MutationObserver 廃止」と出てきます。

ここまで説明しといて廃止かよ!と突っ込まれそうですが、安心して下さい。廃止はされません。少なくとも今のところは。

 

じゃあなぜそんな予測変換が?という話ですが、単純な話でした。

 

 

DOM3まで存在した「Mutation events」が廃止になった

 

ということがあったようです。

同じようなことができる過去のAPIがパフォーマンスと安定性の問題から廃止されて、

それがいつしか混同されてMutationObserverも廃止なの?みたいになっちゃったんですかね。

 

 

DOM4で生まれ変わったMutationObserver

 

パフォーマンス・安定性の問題をクリアして生まれ変わったMutationObserverは現行のDOM4では標準です。

よっぽどのことが無ければ廃止されることはないと思うので安心して使えると思います。

 

どなたかの参考になればこれ幸い。

ではでは。

 

 

※追記:スクロールイベントの救世主、Intersection Observerについても記事にしました

 

Intersection Observerの使い方!時間差スクロールイベントのサンプル付き