関西支店の神庭です。
Sencha Ext JS 6.5.1を使用しているプロジェクトに参加するにあたり、超全体像の説明や個別の詳細は多くありますが、その間をつなぐ粒度の日本語による説明が見つけられず苦労しました。そのため、それを埋める記事という位置づけで記述しようと思います。本記事にすべてを記述することはせず、全体像と読むべき場所を示していきます。
Proxy
データの在処を示す。たとえばREST APIのURLを指定したり、LocalStorageを指定したりする。また、Proxy内にReader/Writerを記述しデータの形式を示す。たとえばJson、xmlなど。
公式で推奨されている通り、通常はModelに記述すればよい。
しかしStoreに記述しなければならない状況も一応存在する。使い分けが気になる人はModel/StoreとProxyの関係にある詳細比較を読むとよい。
Model
データの構造を示す。ProxyをModelに記述していれば、Model単体でデータ読み込み(load)、データ保存(save)もできる。
Modelのfieldsに示されている通り、ModelはExt.data.field.Fieldの配列によってデータ構造を定義する。したがって、設定できるフィールドの種類が知りたいときは、Ext.data.ModelではなくExt.data.field.Fieldを読むとよい。たとえばcalculateなら別フィールドのデータをもとに計算した結果を値として持つフィールドを作成できることがわかる。
Store
データをModelインスタンスの集まりとしてクライアント側でキャッシュしたものであり、Filter、Sort機能をもつ。データ直書き以外でStoreを使う場合は、ProxyとModelの情報が必要である。しかしModelにProxyを記述したケースにおいてはStoreにProxyを記述する必要がなく、Storeのmodelに使用するModelだけ指定すればよい。
Storeのloadは、Proxyで設定したデータソースからModelで設定した構造でデータ群を取得する。初期設定においてStoreインスタンスの生成後の初回loadは自動で行われないことに留意する必要がある。もしそれを自動で行いたい場合、autoLoadをtrueにするとよい。
Storeに変更を加えたのちsyncを使用すると、Storeとデータソースの状態を同期する。
ViewController
主にViewのイベントハンドラを記述する。controlではExt.ComponentQueryを用いたセレクタ形式で下層View全てを対象にListenする。listenersでは自分と対応するViewのみを対象とする。
これに関しては公式のViewControllerガイドを日本語訳した「Ext JS 5 の ViewController を使う」がよくまとまっている。
ExtJSライブラリのコンポーネントから発火されるイベントを知りたいときは、公式リファレンスの「events」を頑張って読むのが面倒なように思えても一番早い。例: Ext.Componentのevents。慣れれば名前だけで発火条件が予想できるようになるから頑張ろう。
View
見た目。Ext.Widgetの派生クラスを組み合わせて生成する。
通常はWidgetの派生クラスであるExt.Componentを継承して必要なコンポーネントをいくつか作成し、Ext.Componentの派生クラスであるExt.Containerにレイアウトしながら詰めていく。レイアウトに関しては、「【まとめ】Ext JSで困ったときに見るサイト等」、「No.7 レイアウトモデル」が参考になる。これはExtJSに限らない話だが、px指定よりflex指定の方が文字通り柔軟なページを作れる。とりあえず上記リンクを斜め読みして、作りたいレイアウトが既に存在するならそれを使う、なければHBoxとVBoxを組み合わせてflexでサイズ調整すれば大体いい感じになる。
また軽量であるWidgetを作りたいときは「Ext JS 5 の ウィジェットを理解する」が参考になる。
Viewに対応するViewControllerの指定は、ViewControllerで「controller」をprefixとするaliasを作成し、対応させたいViewのcontrollerに設定する。例えば「HogeController」でalias: controller.hoge
と設定し、「HogeView」でcontroller: hoge
とすれば関連付けることができる。
xtypeについて
xtypeは、エイリアスを設定したコンポーネントを、必要になったタイミングで生成する際に使われるものである。この機能は遅延インスタンスと呼称されており、「No.6 コンポーネントモデル」の「遅延インスタンス」項目が参考になる。たとえばContainerのitemsにおいて、xtype指定でコンポーネントを配置できる。
xtypeによる遅延インスタンスを行うためには、コンポーネント定義時(Ext.define)にwidgetをprefixとしたエイリアス設定をする必要がある。例えばalias: widget.hoge
のように。
Ext.define直下のxtypeは遅延インスタンス生成ではなく、エイリアス設定のwidget省略記法である。たとえばalias: widget.hoge
とxtype: hoge
はどちらも同じ効果をもたらす。特に理由がなければ、コンポーネントのエイリアス設定はaliasではなくxtype記法を用いたほうがすっきりしてよい。
要は実用の上では、次のようになる。
- 使いたいコンポーネントのxtypeを調べる。またはコンポーネントを作ってxtypeを定義する
- ContainerのitemsConfigなどの要素としてxtypeでコンポーネントを配置する
- 配置したコンポーネントのAPIを読みながら、設定したいConfigをxtypeと同階層に記述する
補足
既存のソースがMVCで記述されていたため、本記事はそれに寄った説明となりました。しかし近年ではMVVMという構造が使われることがあり、Sencha ExtJSにもMVVMで設計するための機能が備わっています。それに関しては、今後使う機会があればまたまとめようと思っています。(ExtJSでのMVVMに関して参考:Sencha Blog Ext JS 5 の MVC と MVVM について)。