モチベーション
背景
クライアントサイドJavaScriptで監視コントローラー付MVCを実装したくなった時の話です。
イベント名をどうやって設計するか?
今はイベントエミッターを実装することは簡単です。
Browserifyを使っていれば、Node.jsのEventEmitterがそのまま使えます。
しかし、イベント名の設計はアプリケーションごとに行う必要があります。
ある程度汎用的な設計は可能でしょうか?
Backbone.jsに学ぶ
Backbone.jsには組み込みイベントがあります。
Backbone.jsはreactほどではありませんが、Reactの次ぐらいに人気があるJavaScriptフレームワークです。
http://www.npmtrends.com/react-vs-angular-vs-backbone
これに学べば、良いイベント名がわかるでしょう。
イベント名
Backbone.jsの組み込みイベントは、Catalog of Built-in Eventsに一覧があります。
ここでは、Backbone.ModelとBackbone.Collectionの操作に関わるイベントのみを扱います。
サーバとの通信、Backbone.Routerに関わるイベントもありますが、扱いません。
BackboneにはBackbone.Modelという一つのデータを扱うクラスとBackbone.Collectionという複数のデータを扱うクラスがあります。
Backbone.Modelのイベント
change
when a model's attributes have changed.
モデルの一つの属性を変更したとき
change:[attribute]
は、特定の属性を変更した時
destroy
when a model is destroyed.
一つのモデルを破壊した時
invalid
when a model's validation fails on the client.
一つのモデルのバリデーションに失敗した時
Backbone.Collectionのイベント
add
when a model is added to a collection.
一つのモデルをコレクションに追加した時
remove
when a model is removed from a collection.
コレクションから一つのモデルを削除した時
update
single event triggered after any number of models have been added or removed from a collection.
コレクションから幾つかのモデルが追加または削除された時に一つのイベントを送出
reset
when the collection's entire contents have been reset.
コレクションの全内容をリセットした時
sort
when the collection has been re-sorted.
コレクションを並べ替えた時
特殊なイベント
Backboneのイベントエミッターにはちょっと変わった仕組みがあります。
all
this special event fires for any triggered event, passing the event name as the first argument followed by all trigger arguments.
どのイベントが発火した時も発火する。
第一引数で発火元のイベント名、以降の引数でイベントと引数を渡します。
使用例
これを使っているのがBackbone.Collecitonの次の機能です。
Any event that is triggered on a model in a collection will also be triggered on the collection directly, for convenience.
コレクション中の各モデルで発火したイベントは、コレクションでも発火します。
これは便利だからです。
CollectionにModelを追加する際に、all
イベントを監視しています。
model.on('all', this._onModelEvent, this);
イベントエミッターオブジェクトで階層構造を組んだとき、イベントを中継したくなることがあります。all
イベントを使うと中継の実装が簡単になります。とても興味深い設計です。
まとめ
ドメインモデルに最低限必要なイベント
Model
change
Collection
add
remove
reset
あると便利なイベント
Model
destroy
ViewとModelが1対1で対応する時に、Collectionを監視せずに済みます。
invalid
モデルでバリデーションする場合、(MVCの)Controllerで制御せずに、ViewがModelを監視して表示を変更できます。
Collection
update
一回の操作で、複数のModelが削除される際に、レンダリングをまとめられます。高速化に役立ちそうです。
sort
順序つきのデータを扱う時に便利です。