LoginSignup
0
0

StimulusはどのようにしてDOMの変更を検知しているのか

Posted at

はじめに

本記事は錆びかけた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の中身のコードではありません。

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ライブラリなんですね。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0