はじめに
本記事は錆びかけたRailsの知識を頑張ってアップデートするアドベントカレンダー10日目です。
今日はMutationObserverについて学んだらRails7(というか、Stimulus)の仕組みが把握できたという話を書きます。
背景
筆者は現在、Rails7のHotWireを学んでいます。
HotWireを学ぶ教材として、猫Rails様の書かれた猫でもわかるHotwire入門 Turbo編を読み手を動かしています。
その中で、Stimulus
というライブラリが登場しました。
stimulusとは?
Railsで利用するJavaScriptのライブラリです。Stimulusを使えば、RailsでJavaScriptを使った動きをつけるとき、より便利にJavaScriptを扱えるようになります。
具体的なStimulusの動作例は以下のページに端的にまとまっているのでぜひご覧ください。
素のJavaScript(ここではバニラJSと呼びます)を利用する場合と比較したStimulusの特徴は以下の通りです。
構造化されたJavaScriptコードの管理
バニラJSもStimulusも、要素に対してイベントをセットして、ユーザーの決まった動作(Clickやフォームの入力)に反応してそのイベントが動く(イベントが発火する)という点は変わりません。
しかし、Stimulusはイベントをセットするためのお作法、レールを用意してくれます。これにより複数人で開発する場合やコードの量が多くなってきた場合でもコードの可読性を保ちやすくなります。
DOMの変更に対する自動的な対応
StimulusはDOMの変更を監視します。新しく要素が追加された場合、自動的に適切なイベントをセットする仕組みがあります。
新しい要素がユーザーの操作などによってDOMに追加される場合、その新しいDOMにイベントをセットするようコードを書くのは手間ですし、ミスが起きやすくなります。Stimulusは、これを自動化しているので便利!ということですね。
疑問点
ここで1つ疑問が浮かびました。StimulusはどのようにしてDOMの変更を監視しているのでしょうか。
結論
Stimulusは、MutationObserver
というものを使ってDOMの追加・更新を監視しています。
MutationObserverとは?
MutationObserverはWeb標準のAPIです。DOMの変更に反応して発火します。JavaScriptから利用するための書き方が準備されています。おそらく、以下のような形で実装されているはずです。
注意: 以下は筆者の妄想コードです。実際のStimulusの中身のコードではありません。
import { Application } from "stimulus"
const application = Application.start()
// MutationObserverの設定
const observer = new MutationObserver(mutations => {
mutations.forEach(mutation => {
if (mutation.type === 'childList') {
mutation.addedNodes.forEach(node => {
// 新しいノード(DOM要素)が追加された時にコントローラーを接続
application.connectControllerForNode(node)
})
mutation.removedNodes.forEach(node => {
// ノードが削除された時にコントローラーを切断
application.disconnectControllerForNode(node)
})
}
})
})
// ObserverをDOMの変更を監視するように設定
observer.observe(document.body, { childList: true, subtree: true })
ここで伝えたいことは、new MutationObserver
という書き方は特にライブラリを読み込まずともできる、つまり標準で使えるクラスであるということです。
なるほど確かに、このようなAPIがあるのならDOMを監視して何かをするということが容易にできそうですね。
Stimulusが監視しているイベントまとめ
イベント | 説明 |
---|---|
input | 入力フィールドに文字が入力された際にトリガーされる。テキストボックスやテキストエリアでのキータイプなどに用いられる。 |
change | フォーム要素(例えばテキストボックス、セレクトボックス、チェックボックス)の値が変更されたときにトリガーされる。 |
submit | フォームが送信されるときにトリガーされる。フォームの送信ボタンが押された際などに反応する。 |
mouseover | マウスポインターが要素の上に移動したときにトリガーされる。 |
mouseout | マウスポインターが要素を離れたときにトリガーされる。 |
keydown | キーボードのキーが押されたときにトリガーされる。 |
keyup | キーボードのキーが離されたときにトリガーされる。 |
focus | 要素がフォーカスを受けたとき(例えばテキストボックスをクリックしたとき)にトリガーされる。 |
blur | 要素がフォーカスを失ったときにトリガーされる。 |
終わりに
StimulusはRailsの思想であるCoCを体現するJavaScriptライブラリなんですね。