動的ウェブアプリケーションのための変更監視手法:”MutationObserverとEvent Listenerの使い分け”
Photo by Christopher Burns on Unsplash
どうも、システムエンジニアの吉森です。
ウェブテクノロジーが進化する中で、動的なウェブアプリケーションが増加しています。そのため、ページの変更をリアルタイムで監視/応答することが重要になっています。アプリケーションによってはバニラJS(フレームワークなしのJS)でコードを書く場面も出てきますが、そういった際によく使うことになるであろういくつかのアプローチについて紹介したいと思います。
本稿では、主にEvent ListenerとMutationObserverを比較してどのような場面でどちらを使用するかに関して言及していきます。
Event Listener
Event Listenerとは?
まずJavaScriptの基本とも言っていいEvent Listenerですが、変更の監視に関して、主に種類は以下の通りです:
- change: inputタグやselectタグ、textareaタグなどのフォーム要素が変更されたり、フォーカスが外れた際に発火します。
- input: 入力フィールドに入力している最中にリアルタイムで発火します。
Event Listenerの使用例
実際の使用例としては、以下のようにターゲットを取得し、Event Listenerを付与することで変更があった際にログ出力されます。
*使用方法:以下をhtmlファイルに貼り付けて、Live Serverを起動することによりログを確認できます。インプットタグに入力するとログ出力されるようになっています。
<body>
<input id="targetId" type="text">
</body>
<script>
const el = document.querySelector('#targetId');
el.addEventListener('input', function(e) {
console.log(`変更点: ${e.target.value}`);
});
</script>
Mutation Observer
Mutation Observerとは何か?
Mutation ObserverはDOMの変更を監視するAPIです。Mutation Observerを使用することで、DOMツリーの変更を検出し、それに応じた動作を後続で実装することが可能になります。
*使用方法:以下をhtmlファイルに貼り付けて、Live Serverを起動することにより開発者ツールよりログと属性を確認できます。ボタンを押すとログ出力されるようになっています。
<body>
<div id="targetId" attr="1" type="text"
style="background-color: aqua; width: fit-content; padding: 10px; margin: 5px 0px; border-radius: 5px;">Target Div
</div>
<button onclick="toggleAttr()">Toggle Attribute!</button>
</body>
<script>
const exampleObserver = () => {
const target = document.getElementById("targetId");
const observer = new MutationObserver(mutations => {
mutations.forEach(mutation => {
if (mutation && mutation.type === "attributes") {
console.log("Attributes が変更されました。");
// この後続で必要な処理を加えることができる。
}
});
});
// 以下で監視したい属性や変更点などを細かく設定します。
observer.observe(target, {
attributes: true,
subtree: true,
characterData: true
// その他にも設定事項はたくさんあります。興味のある方は以下リンクを確認ください。
});
}
////***** ↓属性を入れ替えるファンクション *****/////
const toggleAttr = () => {
const target = document.getElementById("targetId");
target.getAttribute("attr") === "1" ? target.setAttribute("attr", "2") : target.setAttribute("attr", "1");
console.log(`attr属性の値を "${target.getAttribute("attr")}" へ変更`);
}
window.addEventListener("load", (event) => {
exampleObserver();
});
</script>
この例では、要素のAttributesが変更されているか否かを監視しています。これにより、Event Listenerでは発火のできないUIの変更なども監視することが可能になります。
いつどちらを使用するべきか?
- フォーム要素の変更を検出する場合:シンプルなフォームの値の変化を監視するには、
change
やinput
を使用します。 - DOM構造の変更を検出する場合:ページの構造自体の変更を監視する必要がある場合、
Mutation Observer
が適しています。
おまけ(ポーリング)
ポーリングによる変更の監視
上で明記した二つ以外にもいくつか変更を確認する術はありますが、ポーリングはその中でも簡単に実装できるので、特定の場面によっては便利に使用することができます。
下記のコードではtargetが変更されることを毎秒確認しています。これだけだと、わざわざポーリングを使用する必要がないように見えますが、DOM以外の変更やサードパーティーのスクリプトが管理をしている範囲の変更を監視する場合は、とても便利なアプローチとなっています。
ただ補足として、ポーリングはCPUリソースを多く消費するため、使用箇所をしっかりと考慮して使用する必要があります。
*使用方法:以下をhtmlファイルに貼り付けて、Live Serverを起動することによりログを確認できます。インプットタグに入力するとログ出力されるようになっています。
<body>
<input id="targetId" type="text">
</body>
<script>
const exampleInterval = () => {
const target = document.getElementById("targetId");
let lastValue = target.value;
setInterval(() => {
console.log('監視中...'); // 一秒ごとにログ出力されます。
if (target.value !== lastValue) {
lastValue = target.value;
console.log('以下の変更がありました:', lastValue); // 変更があった際にログ出力されます。
}
}, 1000);
}
window.addEventListener("load", (event) => {
exampleInterval();
});
</script>
まとめ
- Event Listenerは、フォーム要素の値の変化をリアルタイムで監視するのに適しています。特に
input
やchange
イベントがこれに該当します。 - Mutation Observerは、DOMの構造や属性の変更を監視するのに適しています。複雑なUI変更や動的な要素の追加・削除を検出する際に有効です。
- ポーリングは、定期的にチェックすることで変更を検出する方法で、サードパーティーのスクリプトが管理する要素やDOM外の変更監視に有効です。
いかがだったでしょうか?それぞれのアプローチを、適切に使い分けることで、より効率的に動的なウェブアプリケーションを構築できるのではないでしょうか。