はじめに
私は、StimulusをRailsで使うとき、stimulus-rails gemをインストールします。
そして、以下のコマンドを実行してStimulusを使う環境を整えます。
./bin/rails stimulus:install
このコマンドを実行すると、複数のファイルが作成されます。
このファイルがあるおかげで、Stimulusが気軽に使える状態になります。
作成されるファイルの中に、Stimulusアプリケーションを起動している以下のファイルがあります。
import { Application } from "@hotwired/stimulus"
const application = Application.start()
// Configure Stimulus development experience
application.debug = false
window.Stimulus = application
export { application }
Application.start()で、Stimulusアプリケーションを起動しています。
このおかげで、Stimulus controllerがいい感じに使えるようになってるのだろうと推測できます。
実際のところ、Application.start()は何をしているのでしょうか?
Application.start()は何をしているのか?
static start メソッド
Application.start()で呼び出されているのは、static startメソッドです。
static startメソッドは、Application classのインスタンスapplicationを作り、startメソッドを実行しています。
static start(element?: Element, schema?: Schema): Application {
const application = new this(element, schema)
application.start()
return application
}
constructor メソッド
Application classのconstructorは以下のように定義されています。
constructor(element: Element = document.documentElement, schema: Schema = defaultSchema) {
this.element = element
this.schema = schema
this.dispatcher = new Dispatcher(this)
this.router = new Router(this)
this.actionDescriptorFilters = { ...defaultActionDescriptorFilters }
}
仮引数elementに何も渡さなければ、<html>要素がelementプロパティに代入されます。Stimulusアプリケーションを適用する範囲を指定したい場合は、仮引数elementに何らかのDOMを渡せば良いということです。
仮引数schemaに何も渡さなければ、defaultSchemaがschemaプロパティに代入されます。defaultSchemaは、Stimulusで使われるキーワードが定義されているオブジェクトです。例えば、HTMLタグにhelloというStimulus controllerを適用する場合、HTML要素の属性にdata-controller="hello"をセットします。このときに使うキーワードが、defaultSchemaで定義されています。
適用するStimulus controllerを指定するキーワードを変えるようなことはあまりないと思います。最も使いそうなユースケースは、action descriptorのカスタマイズです。action descriptorとは、下記<div>要素のkeydown.escの部分です。これは、「Escキーを押したとき」という意味です。デフォルトでは、「@キーを押したとき」という意味のaction descriptorはありません。これを追加したい場合は、defaultSchemaをカスタマイズして、constructor メソッドの仮引数schemaに渡します。
<div data-controller="modal"
data-action="keydown.esc->modal#close" tabindex="0">
</div>
constructor メソッドでは、以下のプロパティの初期化もしています。
routerdispatcheractionDescriptorFilters
router、dispatcherがどういうものなのかは、まだ読み解けてないのですが、大雑把に以下のような役割があるようです。
-
router: DOMの監視 -
dispatcher: DOMイベントとstimulus controllerのメソッドの紐付け
actionDescriptorFiltersでは、DOM event listener optionsにないStimulus独自のoptionを定義しています。
async startメソッド
async startメソッドは、static startメソッドで実行されています。domReady関数を使って、DOMが読み込まれるまで待ちます。その後、dispatherとrouterを起動しています。
async start() {
await domReady()
this.logDebugActivity("application", "starting")
this.dispatcher.start()
this.router.start()
this.logDebugActivity("application", "start")
}
おわりに
Stimulus アプリケーションの起動時に、以下のことをしていることがわかりました。
- Stimulusで使われるキーワードを定義
-
Routerを起動 -
Dispatcherを起動
Router、Dispatcherについては、それぞれどのような目的を持つものなのかはっきりわかりませんでした。
なので、今後は、これらがどのように動いているのか調べてみたいと思います。