こんにちは、ハブラフチャン。 カスタムコンポーネントの作成のトピックを続けて、オブジェクトのプロパティの継承とイベントハンドラーの適切な使用について本日お話します。
プロジェクトが単純な「グリッドとボタンのあるフォーム」から複雑なRIAアプリケーションに成長するとき、インターフェイスの一部をコンポーネントにする必要があります。 ExtJS開発者は、特定のパネルの設定全体をextendステートメントに入れるだけです。
var MyPanel = Ext.extend(Ext.Panel, { items: [{ xtype: 'grid' ................................................... * This source code was highlighted with Source Code Highlighter .
var MyPanel = Ext.extend(Ext.Panel, { items: [{ xtype: 'grid' ................................................... * This source code was highlighted with Source Code Highlighter .
var MyPanel = Ext.extend(Ext.Panel, { items: [{ xtype: 'grid' ................................................... * This source code was highlighted with Source Code Highlighter .
var MyPanel = Ext.extend(Ext.Panel, { items: [{ xtype: 'grid' ................................................... * This source code was highlighted with Source Code Highlighter .
var MyPanel = Ext.extend(Ext.Panel, { items: [{ xtype: 'grid' ................................................... * This source code was highlighted with Source Code Highlighter .
var MyPanel = Ext.extend(Ext.Panel, { items: [{ xtype: 'grid' ................................................... * This source code was highlighted with Source Code Highlighter .
また、Firebugコンソールで最もかわいいエラーを受け取ります(または、このツールがインストールされていないのに何も表示されないのは不思議ではありません)
ExtJSフォーラムのドキュメントを読んだ後、そこで推奨されるソリューションを使用します。
- var MyPanel = Ext.extend(Ext.Panel、{
- initComponent: function (){
- Ext.applyIf( this 、{
- アイテム:[
- ..............................
- });
- MyPanel.superclass.initComponent.call( this );
- }
- ....................................
*このソースコードは、 ソースコードハイライターで強調表示されました。
今ではすべてが機能し、誰もが幸せです。 しかし、残念なことに、誰も疑問に思っていません。なぜこの方法でしか解決できないのでしょうか。 しかし、無駄に。 実際、後で、独自のコンポーネントがオブジェクトまたは配列(たとえば、AJAX要求のパラメーター)である追加のプロパティを表示し始めると、「面白い」バグが必ず発生します。 次の例を考えてみましょう。
- Ext.ux.BadForm = Ext.extend(Ext.Panel、{
- ボーダー: false 、
- フレーム: true
- メッセージ:{
- こんにちは: 'Hello、World!'
- }、
- html: 'Bad Form' 、
- ボタン:[{
- テキスト: 「言う」 、
- ハンドラー: function (){Ext.Msg.alert( 'Message' 、 this .ownerCt.ownerCt.messages.hello); }
- }、{
- テキスト: 'Change Msg' 、
- ハンドラー: function (){ this .ownerCt.ownerCt.messages.hello = 'New Hello Message' ; }
- }]
- });
*このソースコードは、 ソースコードハイライターで強調表示されました。
このようなパネルの2つのインスタンスを作成すると、非常に興味深いエラーが発生します。 [Say]ボタンを押すと、両方のフォームに標準メッセージ「Hello、World!」が表示されます。 ただし、いずれかのメッセージを変更すると、別のメッセージも変更されます。 クラスの2つの異なるインスタンスがある場合、どのようになりますか?
すべてが非常に簡単に説明されています。 JavaScriptには、クラスとオブジェクトのような明確な区別はありません。 すべてのフレームワークは通常、通常のOOP継承スキームをエミュレートし、Ext.extend()/ Class.create()/ new Class()(Ext JS / Prototype / MooTools)などのツールを提供します。 実際、各オブジェクトはプロトタイプに基づいて構築されます。 プロトタイプはすべてのものです。
Ext.extend()メソッドのオブジェクトリテラル内に配置したすべてが適用されます
オブジェクトのプロトタイプ(「クラス」)ですが、メソッドの内容はオブジェクトのレベル(「クラスインスタンス」)で実行されます。
オブジェクトを作成すると、プロトタイプの内容がオブジェクトに転送されます。 ただし、同時に、スカラープロパティ(数値、文字列)のみが実際にコピーされます。 オブジェクトのプロパティとメソッドは参照渡しされます。 作成されたオブジェクトには、事前定義されていない場合、プロトタイプのすべてのプロパティが表示されます。 ただし、JavaScriptで指定されるすべての型はオブジェクトであり、参照によって転送され、スカラーのみが不変です(プロトタイププロパティの正しい解釈についてはmbezoyan
habrayuzerに感謝します)。 したがって、「クラス」BadPanelのすべてのインスタンスのレベルで、メッセージの数は同じメモリ領域を指します。 また、1つのインスタンスからメッセージを変更すると、全員に影響します。
このようなエラーを防ぐには、initComponentメソッドでオブジェクトのプロパティを初期化します。 GoodFormの「クラス」で行われているように、プロトタイプレベルではなく、オブジェクトレベルで:
- Ext.ux.GoodForm = Ext.extend(Ext.Panel、{
- ボーダー: false 、
- フレーム: true
- initComponent: function (){
- Ext.applyIf( this 、{
- メッセージ:{
- こんにちは: 'Hello、World!'
- }、
- ボタン:[{
- テキスト: 「言う」 、
- ハンドラー: function (){Ext.Msg.alert( 'Message' 、 this .messages.hello); }、
- スコープ: これ
- }、{
- テキスト: 'Change Msg' 、
- ハンドラー: function (){ this .messages.hello = 'New Hello Message' ; }、
- スコープ: これ
- }]
- });
- Ext.ux.GoodForm.superclass.initComponent.call( this );
- }、
- html: 「良い形」
- });
*このソースコードは、 ソースコードハイライターで強調表示されました。
また、継承の可能性が侵害されていないことにも注意してください。 Ext.applyIfメソッドが使用されます。 彼は存在しないプロパティのみを確立します。 したがって、GoodFormオブジェクトの作成中に、設定を介してメッセージ(メッセージ)のセットを渡した場合、上書きされません。
リンク
http://habrdemos.ibpro.com.ua/shared-resources-demo.htmlを使用すると、「良い」フォームと「悪い」フォームがどのように機能するかの例を表示できます。
PSお気付きのように、initComponentメソッドのボタンの初期化により、メッセージテキストの受信を簡素化できました。 ただし、これについては、イベントハンドラに関するシリーズの次の記事で説明します。