この記事は、 Sencha Advent Carendar 2014 の16日目の記事です。 @martini3oz がお届けします。
新しいことを覚えるというのは、大変ですが楽しいものです。
僕も先日、新しい体験をしました。THE KIDDIE というロックバンドのライブを観に行ったのです。 それはもう、これまで全然知らなかった世界でした。 とても新鮮でしたし楽しかった。KIDDIE サイコー。揺紗くんサイコー、ユウダイくんサイコー!
あ、Sencha の話でした…
Ext JS 5 から導入された ViewModel について、どのような使い方をして良いのかよくわからない、という話をよく聞きます。そこで、ViewModel について、解説したいと思います。
ViewModel は、View とデータバインディングするための仕組みです。 この DOM とデータの連携をする仕組みは、Sencha 以外のフレームワークでは大変ありがたく重要な機能のようですが、もともとコンポーネントベースで、データと画面表示の連携がすばらしい Sencha のフレームワークでは、「それって何が嬉しいの?」とか、「別にいらなくね?」という声も聞こえてきそうです。
そうはいっても、結構便利ですし、各コード量も減りますので、是非ご活用下さい。
bind
View に bind
コンフィグを指定すると、そのコンフィグを、ViewModel の値とバインドできます。
バインドさせるときには、バインドさせたいコンフィグを bind
で囲みます。
そして、値の名前を {}
で囲んで指定します。
残念ながら、bind
指定できるのは、全てのコンフィグではありません。
そのコンフィグに setter が存在しているもののみになります。
そりゃそうですよね、setter が無かったら値を設定できませんものね。
また、Sencha 得意のショートハンドというかシンタックスシュガーというかも用意されています。それが、defaultBindProperty
です。コンポーネントによってあらかじめ決められたコンフィグは、bind
と指定するだけで済みます。
例えば、TextField では defaultbindproperty
が value
なので、
と書く代わりに
と書けます。
bind
に指定できるのは、ViewModel で管理している「値」です。その値には大きく3種類あります。
data
ViewModel の中で定義した data
コンフィグの内容は、bind
の値となる代表格です。
ViewModel
View
ViewModel の data
コンフィグの中の値を、ビューのコンフィグにバインドしています。バインドするときには、bind
で囲んでやります。
formulas
data
は値そのものでしたが、formulas
は計算式です。
関数の検査員結果を View にバインドさせるために使います。
関数の引数として渡されるのは (上の例では get という名前になっています)、ViewModel の値を参照できる関数オブジェクトです。値の名前を渡してやると、その値を取得できます。
formulas
は、他の書き方として、bind
指定で結びつける値を指定することもできます。
stores
ストアを ViewModel で管理します。stores
で定義したストアを View の中にある、Grid や DataView とバインドすることができます。
Ext JS 4 までは、Application や Controller の stores
コンフィグを指定すると、ストアのインスタンスをフレームワークが作成してくれましたが、それはアプリケーショングローバルでした。
ViewModel での stores
指定は、View とライフサイクルを共にする、ViewModel によって作られますので、このストアも View とライフサイクルを共にします。
このように指定します。
ストアの構造が結構複雑で、しかもいろんな ViewModel から使われるという場合は、app/store/ 下にストアのクラス定義を書いて、それを ViewModel の stores
から利用することもできます。
その際には、ストアクラスで alias
を指定して、ViewModel 側からは type
指定をすると便利です。
alias
のプリフィックスは store
です。
reference
View のコンフィグに reference
を指定すると、二ついいことがあります。
一つは、ViewController 内から簡単にコンポーネントの参照を取得できることです。
これは、一度取得したコンポーネントへの参照をキャッシュするようになっているので、ComponentQuery よりも高速にオブジェクトを取得できます。
もう一つは、バインドする値として、そのコンポーネントを使うことができる、ということです。 言っている意味がわからないと思うので、コードを見て下さい。
この例では Checkbox に reference
を設定しています。
そして、TextField の hidden にバインドしているのです。
これで、イベントハンドラーを一行も書くことなく、テキストフィールドの表示を切り替える事ができます。
どうす?便利でしょ?
バインド時のオブジェクトの扱い
ViewModel のデータとバインドすると、データが変更されたときに画面が更新されますが、データが、ネストしたオブジェクトの場合には、少し注意が必要です。 ネストしたデータをずっと追いかけているとパフォーマンスの低下を招く場合があるので、標準では、オブジェクトのプロパティの変化はモニタリングされません。
つまり、
こんなデータの場合、leader
の値が変更された場合は、変更が検知されて表示が更新されますが、worker.foo
の値が変更されたときには、変更は検知されず、画面が更新されません。
このような変更を検出するためには、View で bind
指定するときに、deep
コンフィグを true
に設定します。
このように指定しますと、worker オブジェクトのプロパティに変更があった場合にも、このコンポーネントは更新されるようになります。
はい、ViewModel ご理解いただけましたか? 何か質問があったらコメントよろしくお願いします。
明日は、@kotsutsumi さんです。
ピンバック: Ext JS 5 データパッケージ | Sunvisor Lab. Ext JS 別館