Backfire のモデルでかなり広範囲に作業してきたので、これについていくつかの考えがあります。それらのいくつかがあなたのプロジェクトに良いアイデアを与えてくれることを願っています.
メンタルモデルをリアルタイム環境に変える
まず第一に、「すべてのデータがロードされたとき」を知るという考え方から抜け出してください。私たちは今、リアルタイム環境にいます。ゼロから始めて、入ってくるすべてのレコードを更新として扱います。これにより、状態を処理するための多くの時間とエネルギーが節約されます。
遅延レンダリングと DOM バインディング
Backbone を使用すると、遅延レンダリングを実行したくなることがよくあります。つまり、次の条件を論理的に処理したいと考えています。
- すぐにデータの収集を開始しますが、render が呼び出されるまで表示しません
- データが表示されるまで「読み込み中」メッセージを表示する
- 複数のレコードが近くに到着した場合、すべてのレコードを再レンダリングしないでください
頻繁に変更されるデータに対する適切なソリューションは、すべてのレコードを再レンダリングする代わりに、DOM の各ノードを個別に操作するBackbone.ModelBinder のCollectionBinder ツールです。彼らのサイトにはたくさんの例がありますので、ここでは詳しく説明しません。
迅速で汚い解決策としてのデバウンス
Underscore のdebounceメソッドは、複雑なデータ バインディングを必要としない小規模な DOM 操作に最適なソリューションです。約 250 の待機でのデバウンスは私にとってはうまく機能し、データの変更時にレンダリングが常に発生することを保証しますが、連続して大量の更新を取得した場合は 1 回だけです。
Backbone.Firebase.Collection を拡張するコレクションを作成したと仮定すると、次のようなことができます。
var View = Backbone.View.extend({
initialize: function() {
this.listenTo( this.collection, 'add remove', _.debounce(_.bind(this.dataChanged, this), 250) );
},
render: function() {
this._isRendered = true;
/* do all my rendering magic here */
},
dataChanged: function() {
// wait until render has been called at least once
// if so, re-render on any change
this._isRendered && this.render();
}
});
Deferred を使用してロードされたデータを待機する
Backfire の実装では、最初の読み込み時に通知するステートフル メソッドを追加しました。jQuery のDeferredオブジェクトを使用してこれを行いました。sync
次に、コレクションがイベントを発生させるのをリッスンします。
this.collection.once('sync', /* data is loaded */);
Firebase の優れた点は、最初の Firebase.on('child_added'...) の結果 (既存のレコード) が 1 つの大きなまとまりになる傾向があることです。追加のボーナスとして、デバウンスを使用して、最初のクランプが完了した後に「ロードされた」メソッドを起動します。これにより、1 つのレコードを取得せず、ロードを呼び出し、一連の更新に対してすぐに何らかのアクションを実行する必要がなくなります。
これは実装固有であるため、ここでは少し抽象的になりますが、これがその要点です。
// inside my wrapper for Backbone.Firebase.Collection
this.ready = $.Deferred();
// debounce our ready listener so it fires on the tail end of
// the initial update clump which reduces the number of update
// calls on the initial load process considerably
this.readyFn = _.debounce(this.ready.resolve, 250);
// start monitoring for the first series of updates
// this would need to be invoked before the sync is established
this.on( 'add', this.readyFn );
// wait for the data to come in
this.ready.always( _.bind(function() {
// when the ready promise is fulfilled, we can turn off the listener
this.off('add', this.readyFn);
// this is where we trigger the listener event used above
this.trigger('sync');
}, this) );
このソリューションは慎重に使用します。ほとんどの場合、初期ロードを忘れてすべてを空に初期化し、すべてを更新として扱うことで、物事を大幅に簡素化できることがわかりました。
これは、データが存在しない場合に別のビューを表示する必要がある場合にのみ使用します (開始手順など)。