【JavaScript】こっちのjsで行った値変更をあっちのjsで感知したい-MutationObserverを使ってみる
表題の通りです。
地獄のスパゲッティと化してきたjsファイルを分割するにあたって、今までワンストップでやっていた処理を、「こっちは表示を変えるだけ」「表示が変わったらこっちで計算をし直す」に分割したいのですが、イベントリスナーのchangeだと、jsから行った値の変更は感知出来ない。
ということで調べてみたところ、MutationObserverが良さそうということで使ってみます。
結論
html
<html>
<head>
<script defer src="js/set.js"></script>
<script defer src="js/update.js"></script>
</head>
<body>
<div>定数+入力した数字を計算します</div>
<div id="const">20</div>
<input type="number" value="10" id="input">
<div id="result">result</div>
</body>
</html>
js1(画面の値を変更するjs)
let CONST_NUM = Number(document.getElementById("const").innerHTML);
let INPUT_OBJECT = document.getElementById("input");
let RESULT_OBJECT = document.getElementById("result");
function inputCheck(){
INPUT_OBJECT.addEventListener("change", submit)
}
function submit(){
let input_value = Number(document.getElementById("input").value)
let result = input_value + CONST_NUM
RESULT_OBJECT.innerHTML = "result=" + result;
}
window.addEventListener("DOMContentLoaded", inputCheck)
(このサンプルの内容なら、htmlの方にボタン足してonclick="submit()"しときゃ良いんですが、本番ではイベントリスナーで取得したい都合があるのでイベントリスナーを設定する様にしています。また、匿名関数だいきらい教の人間なので一々関数を定義しています)
js2(変更を感知して発火するjs)
function checker(event){
console.log("change!!")
console.log(event)
}
let observer = new MutationObserver(checker);
observer.observe(RESULT_OBJECT,{childList:true})
MutationObserverの使い方
0:変更を感知したときに実行させたい関数を作る
1:new MutationObserver()してインスタンスを作る
2:インスタンスを作るときに、第一引数として0で作った関数を渡す
3:observer.observe(RESULT_OBJECT,{childList:true})で、監視したいオブジェクトと、1つ以上のオプションをセットする
一つずつ見ていきます。
0:変更を感知したときに実行させたい関数を作る
引数としてeventを持つ関数を作ります。このeventの中には、変更内容についての情報が入ってきます。
console.log(event[0])
console.log(event[0].target)
console.log(event[0].target.id)
console.log(event[0].target.innerHTML)
みたいな感じで色々取れます。[0]してるのは、event自体は長さ2の配列で渡ってくるからです。0番目だけあればとりあえず十分。
詳細な中身は、console.log(event)してコンソール見てみてください。
1:new MutationObserver()してインスタンスを作る
2:インスタンスを作るときに、第一引数として0で作った関数を渡す
let observer = new MutationObserver(checker);
そのまんまです。コールバックとして渡すので、引数に渡す時には()は不要です。
3:observer.observe(RESULT_OBJECT,{childList:true})で、監視したいオブジェクトと、1つ以上のオプションをセットする
observer.observe(RESULT_OBJECT,{childList:true})
RESILT_OBJECTは、上のサンプルで
let RESULT_OBJECT = document.getElementById("result");
してたやつです。何らかのgetElementした結果を渡せばOK。
オプションについて
良く使いそうなものは以下の感じ。
childList / 子ノードの変化も監視するか
subtree / 子孫ノードの変化も監視するか
characterData / ノードの文字列部分の変化を監視するか
characterDataOldValue / 文字列部分の、変化前の情報を記録するか
attributes / ノードの属性変化を監視するかどうか
{childList:true, subtree:false, characterData:true}
みたいにオブジェクト(連想配列もどき)作って渡せばOKです。
そのほかの項目についても
ここにまとまっていますが、英語なので
https://pisuke-code.com/mutation-observer-usage/
こちらに日本語の見やすい表がありました。お好きな方で。
あとはこれで、コンソールを開きながら画面上の数値を変更してみると、変更が検知されているのが分かるはずです。やったね。
この記事が気に入ったらサポートをしてみませんか?