DOMを監視して変化があった場合にコールバックを呼び出せるMutationObserverオブジェクトの使い方について
間違った認識をしていたので、自分の反省や同じ間違いをしていて原因を探っている人に向けてこの記事を書きます。
間違いに気づいたきっかけ
次のコードを見てみてください。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
<!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Mutation observerの間違った使い方</title> <script src="https://code.jquery.com/jquery-3.6.3.min.js"></script> <script src="./script.js"></script> </head> <body> <main> <dl> <dt>文字数を数えたい文字列</dt> <dd> <input type="text" id="TextToBeChecked"> </dd> <dt>文字数</dt> <dd> <p id="StringLength"></p> </dd> </dl> </main> </body> </html> |
1 2 3 4 5 6 7 8 9 10 |
$(function(){ let observer = new MutationObserver(function(){ const stringLength = $("#TextToBeChecked").length; $("#StringLength").text(stringLength + "文字"); }); observer.observe(document.getElementById("TextToBeChecked"), { attributes: true, characterData: true }); }); |
実現したいことは、テキストインプットの値が変わった時にその文字列のカウントなど何かしらの処理を行うことです。
ここでは変化の検知のためにMutation Observerを使っていますが、これでは動きません。
なぜならMutation Observerは属性の変化を検知するものであり、プロパティの変化を検知するものではないからです。
属性とプロパティの違い
上のような間違ったコードを書いてしまったのは属性とプロパティを区別できていなったのが原因です。
属性とプロパティとはそれぞれ次のようなものです。
属性:
HTML要素を記述するときに付加するもの。上のHTMLで文字列を入力するのに使ったinput要素においてはtypeやidが該当する。プロパティ:
記述したHTMLを解析して作られたDOMノードが持つもの。#TextToBeCheckedに対応するDOM (document.getElementById(“TextToBeChecked”)) が持つプロパティにはvalueやaddEventListener、prepend、innerHTMLなどがある。
HTML要素を記述するときに付加するもの。上のHTMLで文字列を入力するのに使ったinput要素においてはtypeやidが該当する。プロパティ:
記述したHTMLを解析して作られたDOMノードが持つもの。#TextToBeCheckedに対応するDOM (document.getElementById(“TextToBeChecked”)) が持つプロパティにはvalueやaddEventListener、prepend、innerHTMLなどがある。
テキストインプットの中身が変わった時、それはプロパティの変化ですが属性の変化ではありません。
故にMutation Observerはコールバックを呼び出しません。
結論
Mutation ObserverではHTML要素の属性の変化を監視しますが、DOMのプロパティーの変化は監視しません。
もしDOMのプロパティーの変化は監視したい場合は、setTimeoutを使って定期的に値を調べて変化があった場合に何かしらの処理を行うなどの実装をすべきでしょう。