これまでに、何気なくクラスを作ってきたときに、Ext.defineというのを利用してきました。今日は、このExt.defineとソースコードの関係、クラス定義について見ていきましょう。
クラス定義
クラス定義には、Ext.defineを利用します。
1 2 3 4 5 |
Ext.define('クラス名', { // プロパティ定義 }); |
このような形でクラスを定義します、クラス名は文字列で指定します。
ファイルとクラスの関係
いままで、ビュー、ビューコントローラー、ビューモデルなんかを作ってきましたが、HTMLにscriptタグを書いたりして、ソースコードを読み込む様なことは1度もしませんでした。
Sencha Ext JSのソースコード読み込みは、クラス名に合わせて自動的に行われます。
前の、ビュー、ビューコントローラー、ビューモデルのクラス名を例に挙げると
- MyApp.view.main.Main → app/view/main/Main.js
- MyApp.view.main.MainController → app/view/main/MainController.js
- MyApp.view.main.MainModel → app/view/main/MainModel.js
という風に、クラス名がディレクトリ/ファイル名に合わせて定義されています。 これを、requiresに設定することで、そのクラスが利用される前には、requiresに設定されたクラスファイルは既に読み込みが完了していることになります。
読み込みにいくルートのディレクトリは、app.jsonに記述されていますので、パスを追加することも、その順番も変更することが可能です。上記の場合、app下を読み込みにいっているわけですね。
自動読み込み
上記の様に、勝手に読み込みを行ってくれるrequiresですが、実は開発時(development)の時は、特に記述しなくてうまくうごいちゃったりします。これは、Sencha Ext JSが動作するときに、クラス定義がなければ自動的に読み込む(ランタイム読み込み)からです。
では、なんでわざわざrequiresを書くのでしょうか?
それは、sencha app buildの時に、効果を発揮します。sencha app buildを行う時に、Sencha Cmdは、requiresを解析して、いい感じでファイルの結合順番を判断してくれます。なので、クラスの中で使う、他のクラスは、requiresにちゃんと記述する癖を付けておきましょう。
ちなみに、継承は、extendで指定しますが、extendで指定されたクラスは、requiresに記述する必要はありません。これもrequiresの対象として、Sencha Ext JS/Sencha Cmdが自動的に読み込むからです。
クラス生成
作ったクラス定義は、何かしらの形でクラス生成して利用します。クラスの生成には、Ext.createを利用します。
Ext.createは次のように記述します。Ext.defineと殆ど一緒です。第二引数のオブジェクトリテラルで、Ext.defineで定義された値を書き換えて利用することができます。
1 2 3 4 5 |
var c = Ext.create('クラス名', { // 初期設定 }); |
エイリアスとxtype
もう1つは、エイリアスを利用して、クラスを生成する方法です。既に、buttonやtextfieldをエイリアスで作成しています。 コンポーネント/コンテナーを生成するときに、エイリアエスを指定するのが、xtypeというコンフィグオプションです。これは、クラス定義のaliasに設定されている値を指定するのですが、ちょっとルールがあります。
1 2 3 4 |
Ext.define('MyApp.view.my.MyComponent', { extend: 'Ext.Component', alias: 'widget.mycomponent' }) |
上記の様に、Ext.Component以上のクラスを継承した場合、aliaseに‘widget.XXXX’のように、接頭辞にwidget.を付ける必要があります。こうすることで、上記の場合、Myapp.view.my.MyComponent(app/view/my/MyComponennt.js)が読み込まれていれば、xtype: ‘mycomponent’が利用できるようになるわけです。
いままで、使ってきたbuttonやtextfieldもxtypeで、それぞれのクラスで、widget.buttonや、widget.textfiledと定義されているものを、利用してきたことになります。
ちなみに、aliasを使わずに、xtypeと定義することもできます。
MyButtonを定義してみる
ここまでの知識を使って、Ext.button.Buttonを継承した、MyApp.view.my.Buttonクラスを作ってみましょう! 前回作った、MVVMのサンプルで使っていた、Ext.button.ButtonをExt.view.my.Buttonに変更してみます。
MyApp.view.my.Buttonクラス定義は、以下の様になり、textに’マイボタン’というテキストを指定しています。
1 2 3 4 5 |
Ext.define('MyApp.view.my.Button', { extend: 'Ext.button.Button', xtype: 'mybutton', text: 'マイボタン', }); |
そして、Mainビューに設定していたコンフィグオプションを以下の様に書き換えます。
1 2 3 4 |
{ xtype: 'mybutton', handler: 'onClickMyButton' } |
** text: ‘マイボタン’の設定がなくなりましたね?しかし、使っているxtypeがmybuttonに変わっています。mybuttonは、MyApp.view.my.Buttonの事なので、text: ‘マイボタン’**が最初から適用されていますし、もちろんここで上書きして別な文字列を与えることもできます。
完成したコードが以下になります。
終わりに
どうでしたか?クラスの定義は、
- 文字列でクラス名を指定する
- 第二引数に設定オブジェクトリテラルで設定する
- 生成は、Ext.createを使うことができる
- コンポーネントは、xtypeを使って生成することができる
ということを学びました。
実際に、上記の例ではExt.createを利用していませんでした。コンテナーのitemsにコンポーネント/コンテナーを指定する場合、殆どxtypeで指定することになります。
んじゃ、Ext.createいつ使うんだよ?
ってなりますよね、これはコンポーネントを動的に生成する場合にも利用できますし、コンポーネントクラス以外のクラスを生成して利用するときも使えます。そのうち、コンポーネントの動的生成についても説明したいんですね、実際の業務アプリケーションの場合、itemsに固定のアイテムだけを表示するっていうだけではなくて、取得したJSONデータからフォームを動的に作成しなくてはならないシーンも十分にあり得ます。
が、まだいいんです、シンプルに、使い方解れば。
次回は、コンポーネント/コンテナーって出てきていますが、そもそもそれなんなんだ?っていう話に入って行きます。