ExtJSでソーシャルネットワークのプロトタイプを作成します。 ExtJS 4の最初と最後の問題

絶えず変化する要件と厳しい締め切りにより、ExtJS 4を使用してプロトタイプを作成するようになりました。



開発で遭遇したExtJSの問題は、ExtJSの準備で得た経験をほとんど超えませんでした。



インターネットには、ExtJS 4レベルの基本に関する多くの記事があります。 たとえば、この記事はhttp://css.dzone.com/articles/how-use-extjs-4-jqueryに非常に満足しています 。 しかし、ExtJSを使用したいくつかの問題の解決(または作成)に関する深刻な「非現金」記事は多くありません。



ExtJSパッチラボのフレームワークの最初の記事をお読みになることをお勧めします。 ネットワーク...かなり。







フィードでは、 Ext.panel.GridExt.data.Storeとともに使用することが決定されました 。 これらは、ExtJSの使用を選択した基本的なものであると言えます。



なぜgridであり、 dataViewではないの (後でファイナルはビューを優先してグリッドを放棄しなければならなかった) グリッドは、データの並べ替えとフィルタリングのためのビジュアルモードである「エンドレス」スクロールが気に入っていました。 提供された機会の喜びは、単に圧倒的でした。



Ext.data.Store



データはAPI呼び出しを使用してサーバーから取得され、生の形式でStoreクラスのloadDataメソッドに転送されます。 FoursqureのようなAPIのため、ストアに組み込まれたプロキシは使用しませんでした



var myStore = Ext.create('Ext.data.Store', { model: 'Post', filterOnLoad: true, idProperty: 'id', filters: new Ext.util.Filter({ filterFn: function (item) { return item.get("status") > 0; } }) }); … API.Events.get().done(function(posts){ myStore.loadData(posts); });
      
      





PostモデルはExt.data.Modelクラスの子孫です。



 Ext.define('Post', { extend: 'Ext.data.Model', idProperty: 'id', constructor: function (raw) { return this.callParent([this.prepare(raw), raw[this.idProperty]]); }, prepare: function (raw) { … } });
      
      





Postモデルでは、生データはprepareメソッドを介して準備されます。 親クラスのコンストラクターでは、データは既に処理済みのフォームに含まれています。



prepareメソッドで行われること:

たとえば、投稿日を文字列からDateオブジェクトにキャストする



 this.data = new Date(this.data);
      
      





...通信テーブルのハッシュを介してtypeIdから投稿名の文字列値を取得する



 this.typeName = Dict.post.types[this.typeId];
      
      





などなど...



Storeはインスタンス化されたモデルの形式で自身の内部にデータを保存します。loadDataメソッドは、データがまだ生であるかどうかを確認し、モデルコンストラクターに転送して、配列の各要素でデータを書き込みます。



快適なユーティリティ#1



したがって、 loadDataは生オブジェクトの配列と既にインスタンス化されたモデルの両方を受け入れます。



機能#1



単一のオブジェクトをloadDataに渡すと 、エラーが発生します。メソッドは、1つの要素からであっても配列のみを予期します。



機能#2



javascriptのオブジェクトは参照によって渡されるため、 loadDataに転送される生データはモデルの配列になります。



 API.Events.get().done(function(posts){ //posts is array of objects myStore.loadData(posts); //posts is array of Models });
      
      





そのままロードした後に元のデータが必要な場合は、 Ext.Array.clone()メソッドを使用しますが、このメソッドはjQuery.extendのようなディープクローニングをサポートしていません。



問題#1



loadDataメソッドには、2番目のパラメーターappendがあります (ストアの既存のレコードにレコードを追加するにはTrueを追加し、古いレコードを最初に削除するにはfalseを追加します) つまり 新しい投稿はサーバーから送信されるため、既存の投稿に追加する必要があります。 これを行うには、2番目のパラメーターをtrueに設定します



この場合、ストアはロードフィルタリングを使用します(filterOnLoad = true)



フィルタリングの仕組み:



Storeはすべてのレコードを2つのコレクションに格納します。メインのコレクションはdataで、非表示のコレクションはsnapshotです。 Storeのキー「filterOnLoad:true」は、何らかの方法でデータをロードするときにストアにフィルターを強制的にチェックさせ、内部ストレージでフィルター処理されたスナップショットを破棄します。



Storeでのフィルターの使用とloadDataメソッドは互換性がありません。



ext-all-debug.jsファイルからのリスト( loadRecordsメソッドはloadDataなどで使用されます)



 loadRecords: function(records, options) { … if (!options.addRecords) { delete me.snapshot; me.clearData(); } me.data.addAll(records); … }
      
      





ここに問題があります。この場合、 options.addRecordstrueですスナップショットは削除されず、データはメインコレクションにのみ含まれます。



 API.Posts.get().done(function(posts){ myStore.loadData(posts); //posts.length 8, filtered 2 entries }); … API.Posts.get().done(function(posts){ myStore.loadData(posts, true); //posts.length 10, filtered all entries });
      
      





最初のブートでは2つのエントリのみが通過し、それが2番目のブートですべてです。



me.dataには2 + 10のエントリが含まれ、 me.snapshotには8のみが含まれる 2番目の呼び出しからのデータは、隠されたストレージに入れられませんでした。



コレクションを並べ替えるには、古いフィルターをクリアして新しいフィルターを適用する必要があります。フィルターを「再読み込み」することはできません(非常に奇妙です)。



mystore.clearFilter()メソッドは最後の10レコードを削除します;その結果、リポジトリに8レコードがあります。



解決策



 loadRecords: function(records, options) { … if (!options.addRecords) { delete me.snapshot; me.clearData(); } me.data.addAll(records); //add records in snapshot too. if (options.addRecords && me.snapshot) { me.snapshot.addAll(records) } … }
      
      





問題#2



idPropertyキー 、本来の目的には使用されません。



idPropertyフィールドは、データベースの主キーに相当します。 私たちの場合、データには一意のIDキーがあり、これにより、新しい投稿をリポジトリに追加する必要があります。 投稿を変更する場合、たとえばコメントを追加する場合、リポジトリ内のこのエントリを更新する必要があります。 idProperty = "id"キーが設定された追加モードのloadDataメソッドは、この問題を解決するはずです。 しかし実際には、このキーはこれには使用されず、データのマージを自動化することはできません。



ソースをざっと調べてみると、そのような機能が存在するが、使用されていないことがわかりました。 me.data.addAll(レコード)メソッドは、配列だけでなく、キー値オブジェクトも受け入れることができます。 この機能を使用するには、同じloadRecordsメソッドをわずかに変更するだけです。



解決策



 loadRecords: function(records, options) { … if (!options.addRecords) { delete me.snapshot; me.clearData(); } me.data.addAll(records); if (this.idProperty) { var indexRecord = {}; for (i = 0; i < length; i++) { indexRecord[records[i].data[this.idProperty]] = records[i]; } me.data.addAll(indexRecord); if (options.addRecords && me.snapshot) { me.snapshot.addAll(indexRecord); } records = []; for (key in indexRecord) { records.push(indexRecord[key]); } length = records.length; } else { me.data.addAll(records); if (options.addRecords && me.snapshot) { me.snapshot.addAll(records); } } … }
      
      





これらの変更後、キーとしてid値があり、新しいデータを追加できます。それらは複製されません...



PSあなたの編集でソースにクロールするのが悪いことを忘れないでください、 Ext.overrideを使用してください 。 したがって、フレームワークのバージョンを更新するときに問題を取り除き、パッチファイルを記述するだけで、新しいバージョンで古い問題を修正する場合は、パッチからソリューションを削除します。



将来的には、ストアのプレゼンテーションとの同期の問題を考慮し、複数の表現がある場合はどうなるかを検討します。



アプリケーションは受け入れられますが、さらに興味深い問題とその解決策があるかもしれません。



All Articles