MutationObserver … JavaScript から DOM を監視する新しい方法

  • 2019/2/4
  • MutationObserver … JavaScript から DOM を監視する新しい方法 はコメントを受け付けていません。

JavaScript でページ上の動きを拾うには…?

こんにちは、江嵜です。

みなさん、JavaScript 書いてますよね!

大体 Web アプリ作ってるときに JavaScript 書くとなると、やりたいことって
「テキストボックスに文字を入力されたときにー」とか、
「ボタン押されたときにー」とかだと思うんですけど、
そういった動きはどうやって JavaScript で検知していますか?

そうですね、 on とか addEventListener とか、
動作時に発生するイベントを監視して、そのイベントが発生したときに
何かしらの動作をさせる…というのが普通のやり方かと思います。

例えば、サンプルなんかでよくある「ボタンを押したときにログを出力する」とかだと

const hoge = getElementById('hoge');
hoge.addEventListener('click', function () {
  console.log('ボタンが押された!');
});

みたいなやりかたが普通、ですね。

この辺でカンの良い方はなんとなく、今日の話題が分かってきますね。
そうです。今回はその、普通の方法ではないやり方で、ページ上の動きを検知していきます。

MutationObserver というものが最近追加されました!

イベントでなければどうやるの…?というところで、今回はこちら。
「MutationObserver」を使っていきます。

とりあえず JavaScript で初めて出会ったものは、 MDN でしらべてみましょう。

MutationObserver

MutationObserver とは、指定したコールバック関数を DOM の変更時に実行させる API です。この API は、DOM3 Events の仕様で定義されていた Mutation Events を新しく設計し直したものです。

MutationObserver とは、指定したコールバック関数を DOM の変更時に実行させる API です。

つまり、イメージ的には、これまでイベントを使っていた時は
「文字が入力された!」「ボタンが押された!」という事柄が発生した時に指定した動作をさせていましたが、
このイベントとして「DOM が更新された!」ということをきっかけに指定した動作を実行させることができるということですね。

…ちょっと言葉で説明するの難しいんで、とりあえず例題言ってみましょう。

実践

さて、ササっとコード書いてみます。

今回はこんな感じでー…

HTML

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
</head>
<body>
  <button id="btn">click me</button>
  <div id="target">
  </div>
</body>
</html>

JS

const target = document.getElementById('target');

// MutationObserver 作成
const observer = new MutationObserver(function () {
  console.log(target.children.length);
});

const config = { attributes: true, childList: true, characterData: true };

// 監視実行
observer.observe(target, config);


// ボタンを押したら target 要素内に div を追加する
const btn = document.getElementById('btn');

btn.addEventListener('click', function (e) {
  e.preventDefault();
  const div = document.createElement('div');
  div.textContent = "added."
  target.appendChild(div);
})

ボタンを押したら target ID の要素内に
div が一つ追加される、という内容ですね。

今回のポイントは前半部分。

const observer = new MutationObserver(function () {
  console.log(target.children.length);
});

ここでは MutationObserver を作成して、
変更が起こった際に何をするかを関数で渡してあげていますね。

今回は target 要素内の要素数をコンソールに出力させてみています。

ここでは MutationObserver を作成しても、
まだ実際にどの要素を監視するべきか、ということについては指定していないことに注意。

observer.observe(target, config);

で、こちらですね。
作成した MutationObserver に対して、 observe を実行していますね。
この時、第一引数の方に監視対象となる要素を、
第二引数の方にはオプションを渡してあげます。

実際にこれを実行してみると…
( 今回は https://jsbin.com/ で実行してみています)

確かに、ボタンを押して要素が追加されると同時に、
コンソールの方には 1,2,3 … と数字が出力されていますね!

いいカンジです!

MutationObserver に指定できるオプションは

MutationObserver

MutationObserver とは、指定したコールバック関数を DOM の変更時に実行させる API です。この API は、DOM3 Events の仕様で定義されていた Mutation Events を新しく設計し直したものです。


こちらを見てもらったら分かりやすいかと思います。

要は対象の DOM の子供も監視するかとか、 DOM の属性も監視するかとか、そういった設定ができるようになっています。

MutationObserver の使いどころ

ということで、DOM が更新されたことを検知できる MutationObserver を紹介いたしました。

が、もしかしたらこう思われている方もいらっしゃるかもしれないですね。

「DOM の更新を検知できて何がうれしいの?今回のサンプルだって、結局ボタンがクリックされたときのイベントを使うのと変わらなくない?」

確かにそうですね。
普通にプログラム書いていて、 MutationObserver 使いたい!って思うようなことはまずないかと思います。

ではいつ使うのか…それは…
Browser extension の作成時ですね!

いわゆる、ブラウザの「拡張機能」と呼ばれているヤツです。

Google Chrome ならこんな感じで、右上に小さいアイコンが並ぶ、
ブラウザの機能を拡張してくれるヤツです。

彼らは現在開いているページに対して、便利なボタンを追加してくれたり、
情報を収集してくれたりと便利な機能を提供してくれています。

が、しかし、彼らは言ってしまえば「勝手に」ページに介入しているものですから、詳細な画面の設計などは入手できませんし、それに、様々なページに対応する必要があります。
動的に画面が変わるページでは、イベントを使って正しく変化に追従するのは少し難しいところがあるのですね。

ということで、この MutationObserver を使えば、確実に画面の変換に対応ができる、という事で、とても便利に使うことができるのです!

皆さんも、使ってみると結構便利な MutationObserver 、使ってみてくださいね!

Takato Ezaki

Takato Ezaki小中高の塾講師からエンジニア

投稿者プロフィール

福岡で Web 系のエンジニアをしています。

中高の理科教師免許を取り、起業に 2 年間トライした後エンジニアの道へ入りました。

化学反応の中では Belousov-Zhabotinsky 反応が大好きです。

この著者の最新の記事

関連記事

コメントは利用できません。

募集中!(o゜▽゜)o

エンジャパン
求む、社長!
follow us in feedly

コッチもヨロシク!





最近のネタ!

  1. 2019-4-22

    パスワード管理も入力も劇的にラクに!1Password でパスワード管理しよう!

    詐欺サイトが流行している今だからこそ使いたい、パスワード管理 こんにちは、江嵜です。 最近はスミ…
  2. 2019-4-17

    第8回 麻雀部活動記録~まるで個室のような雀卓で~

    3月末の桜が満開な季節に恒例の麻雀部を開催してきました! 例によって活動記録を書いていこうと思いま…
  3. 2019-4-15

    JetBrains の IDE に新色登場! IntelliJ でも PhpStorm でも新しい色を体験しよう!

    JetBrains の IDE に新しいテーマが作られていました! こんにちは、江嵜です。 みな…
  4. 2019-4-8

    やっぱり JavaScript (TypeScript) でも アノテーション (Decorator) 使いたい!

    JavaScript でもアノテーションしたい! こんにちは、江嵜です。 JavaScript …
  5. 2019-4-3

    2019年03月度社員総会&懇親会@Tokyo☆

    2019年3月15日(金)に、エージェントグロー東京オフィスの社員総会&懇親会が開催されまし…
ページ上部へ戻る

当サイトに掲載されているコンテンツ(文書、画像等)は、許可なく複製・転用等する事を禁じます。

「フェアネス方式」は、株式会社エージェントグローが日本国内において出願中の商標です。

当サイトでは最低限必要と考えられる場合において、会社名/サービス名/商品名などを記載している場合があります。
これらはあくまでも説明の必要性に応じて用いているものであり、各社の権利等を侵害を目的とするものではございません。
不適切と考えられる場合には、当社お問い合わせフォームよりご連絡ください。

当サイトでは®や™などの表記を省略させていただいております。