Contenu connexe
Plus de Yuki Naotori (20)
外部ライブラリのExt.Component化
- 2. ⽬次
外部ライブラリをComponent化する意義
p
取りこむ⼿法
◦ 継承
◦ プラグイン
継承のスタイル
◦ Component
◦ ⾮Component
親クラスを選ぶ
◦ Ext.Component
◦ Ext BoxComponent
Ext.BoxComponent
◦ Ext.Container
外部ライブラリの取り込み例
◦ Mac OS-Style Dock
l k
◦ flot
さらなる拡張にむけて
- 3. そもそもExt Componentとは…
そもそもExt Componentとは…
そもそもExt.Componentとは
Ext.Componentとは
「Ext 2.0 - API ドキュメント & チュートリアル」⽇本語版
(http://docs.ext-japan.org/docs/)によれば…
(h //d /d /)によれば
◦ 全てのExtコンポーネントに対する基本クラス。 コンポーネント
の全てのサブクラスは、⽣成、レンダリングそして消去からなる
全 サブク は ⽣成 ダリ グ 消去からな
標準 Ext コンポーネントのライフサイクルにおいて⾃動的に関
与することが可能です。 それらはまた、表⽰/⾮表⽰、有効/
無効という基本的なビヘイビアに対する⾃動的 なサポートをも
有します。コンポーネントはどんなサブクラスでも
ポ ブ
Ext.Container への遅延表⽰(※lazy-render)を可能とし、ま
た、コンポーネントはいつでも Ext.getCmp を通じて参照する
ことが可能となるように、⾃動的に Ext.ComponentMgr に登録
t Co po e t g
されます。レイアウトの中にレンダリングを要する全ての視覚
ウィジェットは、 サブクラス・コンポーネントでなくてはなり
ません(あるいは、ボックスモデル操作が要求されているのなら、
Ext.BoxComponent です)。
◦ あらゆるコンポーネントは getXType や isXType のような
xtype をチェックするメソッドに加えて特定の xtype、すなわち
Ext 特有の型名、を有します。
- 4. つまりExt Componentとは…
つまりExt Componentとは…
つまりExt.Componentとは
Ext.Componentとは
Extにおけるウィジェットの基本単位である
◦ ブラウザウィンドウ上である⼀定の幅と⾼さを占有する
DOMノード管理オブジェクト
幅(w)+⾼さ(h)+位置(x,y,z)
DOMノード + Ext.Element
css スタイル (style or class)
◦ 標準的なGUI SDKと同じウィジェット機能を提供
動的な表⽰・⾮表⽰
動的な有効・無効
動的な幅・⾼さ・その他外観の⼀貫性のある変更
◦ DOMノ ドのライフサイクルを整理
DOMノードのライフサイクルを整理
インスタンス⽣成→レンダリング→破棄
◦ DOMネイティブのイベントを代⾏(Ext.eventMgr)
Ext独⾃イベントとのAPIの統⼀
E t独⾃イベントとのAPIの統
独⾃イベントを定義可能に
◦ Ext独⾃の簡便な継承体系をサポート
JavaScript ネイティヴのデリケ トな継承様式を整理
J S i t ネイティヴのデリケートな継承様式を整理
- 5. …
◦ DOMノードと同期したIDによる管理
Ext.ComponentMgrによる⼀元管理
Ext.id()によるID⽣成
Ext.getCmp() Ext.get() による⼀発検索 (Ext.fly()) Component
単位での他者へのアクセスメソッドを提供
親 : this.ownerCt
⼦ : this.items (Array)
兄弟 : this.ownerCt.items (Array)
◦ JSONツリー → DOMノードツリー変換
煩雑な html + css (=XML)の記述を廃して、簡便でJavaScriptフ
レンドリーなJSONによる設定系IFを提供
xtype でだらだら書ける(Ext.ComponentMgr)
◦ Ext の継承体系への編⼊
サブクラスを定義することができる
◦ Ext.state.Managerによる外観の保存
基本は Cookie に保存(他も独⾃実装できる)
Component.id で管理するので、バージョンアップ時にめためた
になることが…
になることが
- 6. ようするに、外部ライブラリを
Ext.Component化すると…
Ext.Component化
化すると…
前記の機能のすべてを外部ライブラリに
付加することができる
◦ まあ、実際は「その準備ができる」だけで、
実装は⾃分でするんだけど
実装 ⾃分 だ ど
標準のExt Component 群と混ぜ合わせ
標準のE t C t
ることができるようになる
Extの使⽤法を知っている開発者であれ
ば、難なく使うことができるようになる
JSONでの設定系に乗ってくる
APIの使⽤感が統⼀される
- 9. Componentの継承スタイル
Componentの継承スタイル
/** this.template = MyNameSpace.MyComponent.componentTemplate;
* @class MyNameSpace.MyComponent }
* @extends Ext.SuperComponent // Template -> DOM ノードをして、ct もしくは position のあたりに挿⼊
* こんな感じで JsDoc を書くのが Ext ⾵ var cmp, targs = [ʻinnerHtmlʼ, ʻclassʼ];
* @cfg {String} foo This is foo option if (position) {
* @cfg {Number} bar This is bar option cmp = this.template.insertBefore(position, targs, true);
* @constructor } else {
* @param {Object} config The config object cmp = this.template.append(ct, targs, true);
*/ }
MyNameSpace.MyComponent = Ext.extend(Ext.SuperComponent, {
/* // その他、style の設定、イベントの代⾏等
* 適当にデフォルトの設定を列挙する },
* @type String
*/ /**
hoge: “hogehoge”, * パブリックメソッドは JsDoc で
* @param {String}
// private */
initComponent: function() { public_method: function(hoge) {
// 前で、config の状態を⾒ながら補完 this.hoge = hoge;
MyNameSpace.MyComponent.superclass.initComponent.call(this);
this.private_method();
// イベントハンドラ等は、インスタンスができてからくっつける
},
},
// private プライベ トメソッドは // で
プライベートメソッドは
// private
private_method: function(scope) {
// DOM のレンダリングを⾏う
// 親クラスのメソッドを呼び出せる
onRender: function(ct, position) {
MyNameSpace.MyComponent.superclass.private_method.call(scope ||
// テンプレートの準備 this);
if (!this.template) { }
if (!MyNameSpace.MyComponent.componentTemplate) { });
MyNameSpace.MyComponent.componentTemplate = new // xtype に登録する
Ext.Template(ʻ<tag class={1}>{0}</tag>ʼ);
Ext.reg(“mycomp”, MyNameSpace.MyComponent);
}
- 10. Component のサブクラスに
xtype に登録することができる。
◦ Ext.Componentツリーの正式な⼀員に
Ext.extend の引数にすべてを書ける
あらゆるメソッド中で親クラスのメソッドを参照可能
◦ ThisClass.superclass.xxx.call(scope || this);
◦ scope の対応は忘れずに!
親クラスとデフォルト値を変えることができる
◦ extend 中 JSON にまぜこむと上書きされる
中の ぜ 上書き れ
initComponent() の中で⼀括していろいろ初期化可能
◦ 親クラスメソッド呼び出し前
設定やインスタンスの補完
◦ 親クラスメソッド呼び出し後
このクラスの発⾏するイベントの定義
デフォルトのイベントハンドラを追加
レイアウト⼦のインスタンスの状態に応じた処理を追加可能
◦ この段階ではまだDOMノードは⽣成されていない点に注意
this.onRender() を定義 → 正式
this.on(ʻrenderʼ, function() {xxx;}, this); でフック(簡易)
- 11. Component のサブクラスに
プロパティ・コンフィグ・メソッドをフラットに書くことができる
◦ /** は public (JsDoc)
◦ // は private
あらゆる箇所で独⾃のイベントの発⾏が可能に
◦ this.fireEvent(ʻevent_nameʼ, arguments…);
◦ 名前は initComponent 時に事前に与えてあげましょう。→ イベントの整理
に役⽴ちます。
this.onRender でDOMノードを⽣成して、親コンテナに登録する
でDOMノ ドを⽣成して、親コンテナに登録する
◦ DOMノードはExt.Templateで⽣成
html + css class を⽣成
style 指定はきかないっす
キャッシュしてまじめに使いまわすこと
◦ 引数はレイアウト先(DOM挿⼊先)を指している
renderTo applyTo 等、⾶び地を許可しているので。
ct が登録先親DOMノード → append()
position が挿⼊位置 (null なら ct へ)→ insertBefore()
◦ その他、レンダリング後にはじめて設定可能になるようなものを初期化
- 12. レンダリング時にしなければな
らないこと
インスタンス⽣成時は、まだレンダリング(DOMノードの⽣成と
documentツリーへの登録)は⾏われていない。
d tツリ の登録)は⾏われていない
show() や render() メソッドが呼び出されると、そのComponent
に所属している⼦Component が順次レンダリングされてゆく
this.onRender() が共通のレンダリングエントリポイント
◦ 親クラスが E t C
Ext.Component なら superClass.onRender.call(this) は必要な
t Cl R d ll(thi )
い。(Ext.Component.onRender() は Ext.emptyFn)
◦ render イベントを出す必要もなし(上位でやってくれる)
◦ Ext.Template からDOMノードを⽣成
Ext.BoxComponent 以上の場合は、⾃⾝の幅と⾼さ、位置の設定をきちんと反映する
こと
◦ ct もしくは position の前後にDOMノードを挿⼊
◦ Ext.Component ID と Ext.Element ID と DOM ID の三者を同期
p
this.el.dom.id = this.el.id = this.id;
◦ その他、こまごまとした設定
JSON → css Style
DOMネイティヴなイベントの代⾏設定
- 14. ⾮Componentの継承スタイル
Componentの継承スタイル
/**
* @class MyNameSpace.MyClass // Ext.extend でこのクラスを定義する
* @extends Ext.util.Observable // new MyNameSpace.MyClass(); でインスタンスを⽣成できるようになる。
* こんな感じで JsDoc を書くのが Ext ⾵ // この MyNameSpace.MyClass のサブクラスを定義できるようになる。
* @cfg {String} foo This is foo option // Ext.extend の引数は (このクラス、親クラス、メソッド群)
* @cfg {Number} bar This is bar option // メソッドは上のコンストラクタ側で定義してしまうと、
* @constructor // サブクラスに継承されなくなってしまうので こちら側で定義する
サブクラスに継承されなくなってしまうので、こちら側で定義する。
* @param {Object} config The config object Ext.extend(MyNameSpace.MyClass, Ext.util.Observable, {
*/ /**
MyNameSpace.MyClass = function(config) { * パブリックメソッド
// Component でないクラスは、constructor をきちんとつくる * @param {String} foo a new foo to set
config = config || {}; // 引数なし時に対応 * @param {Number} bar a new bar to set
// config をもとに this を適当に初期化。 * @return {Array} new foo and bar to set
this.foo = “foo”; */
this.bar = 0; myPublicMethod: function(foo, bar) {
Ext.apply(this, config); if (typeof foo != “undefined”) {
// 親クラスの constructor を呼んであげる this.foo = foor;
MyNameSpace.MyClass.superclass.constructor.call(this); }
}; if (typeof bar != “undefined”) {
this.bar = bar;
}
this.myPrivateMethod();
return [this foo this bar];
[this.foo, this.bar];
},
// private
myPrivateMethod: function() {
// do something
g
}
});
- 15. ⾮Component のクラス定義
constructor を function で定義する。
◦ 引数は通常 config オブジェクトひとつ
◦ Ext apply 等を駆使して config を this
Ext.apply
に反映しつつ、適切に初期化
Ext.extend
Ext extend の引数は 3つ
◦ 1: 定義するクラス
◦ 2: 親ク
親クラス
◦ 3: メソッド群オブジェクト
constructor 側でメソッドを追加すると、サブ
クラスを定義した際にメソッドが継承されない
ので注意。
ので注意
- 16. 参考⽂献
Ext 2 Overview (Japanese)
◦ http://extjs.com/learn/Ext_2_Ove
rview_(Japanese)
i (J )
Manual:Component:Extension
or Plugin
◦ http://extjs.com/learn/Manual:Co
mponent:Extension_or_Plugin