9

コレクション(Backbone 0.9.2)でfetch()の後に基本的なrender()を実行しようとしています:

var ProjectListView = Backbone.View.extend({
        el: $('#container'),
        initialize: function () {
            this.collection = new ProjectsCollection();
            this.collection.bind("change", _.bind(this.render, this));
            this.collection.fetch({ success: function () { console.log("collection fetched"); } });
            ...
             }, 
        render: function () {
            console.log("rendered");
            ...

新しいViewインスタンスを作成すると、次のように出力されます。

    collection fetched 

したがって、render()はfetch()の後に呼び出されることはありません。私はここで何が間違っているのですか?例外はありません。

バックボーンでこれらの種類のものをデバッグする方法のヒントはありますか?

追伸 SOに関する質問の数を考えると、この機能は十分に文書化されていないようです。

4

3 に答える 3

29

細かいマニュアルから:

フェッチ collection.fetch([options])

このコレクションのデフォルトのモデル セットをサーバーから取得し、到着時にコレクションをリセットします。[...] モデル データがサーバーから返されると、コレクションはリセットされます。

そして、何をしresetますか?resetこれを行います:

リセット collection.reset(models, [options])

[...]リセットを使用して、コレクションをモデル (または属性ハッシュ) の新しいリストに置き換え、"reset"最後に 1 つのイベントをトリガーします。

そのため、コレクションのモデルを更新するためにfetch呼び出し、イベントではなくイベントをトリガーします。どのモデルも変更されておらず、コレクションのイベントはそのモデルから発生しています。resetreset"reset""change""change"

renderにバインドする必要があります"reset":

initialize: function () {
    this.collection = new ProjectsCollection();
    this.collection.bind("reset", _.bind(this.render, this));
    this.collection.fetch(...);
}

含まれているモデルでイベントをリッスンする場合は、ハンドラーをコレクションにバインド"change"できます。"change"

"change"コレクション内のモデルが変更されたときに通知されるようにイベントをバインドできます
。 [...]
コレクション内のモデルでトリガーされるイベントは、便宜上、コレクションでも直接トリガーされます。

コレクション自体が変更されると、コレクションもイベントを生成"add"します。"remove"


Backbone の新しいバージョンでは、次の期間中にコレクションがリセットされなくなりましたfetch:

モデル データがサーバーから返されると、setを使用して、取得したモデルを (インテリジェントに) マージします。渡し{reset: true}た場合、コレクションは (効率的に) resetになります。

そしてset

[...] 渡されたモデルのリストを使用して、コレクションの「スマート」更新を実行します。リスト内のモデルがまだコレクションにない場合は、追加されます。モデルがすでにコレクションにある場合、その属性はマージされます。リストにないモデルがコレクションに含まれている場合、それらは削除されます。これが発生すると、適切な"add""remove"、および"change"イベントがすべて発生します。

そのため、Backbone の新しいバージョンでは"add"、 、"remove"、および"change"イベント (いずれにせよ、コレクション ベースのビューがリッスンする必要があります) を一覧表示する必要があります。{reset: true}イニシャルで使用してfetch聞くこともでき"reset"ます。コレクションベースのビューには、次のアプローチをお勧めします。

  1. ビューに 1 つのアイテムを追加するだけのコールバックを使用して、そのイベントをリッスンし"add"て処理します。すべてを破棄して再レンダリングしないでください。
  2. "remvoe"新しく削除されたモデルのみを削除するコールバックで、そのイベントをリッスンして処理します。
  3. "change"適切な項目を置き換える (または更新する) コールバックをリッスンして処理します。
  4. を聞いて"reset"、それを にバインドしrenderます。{reset: true}次に、コレクションの最初のfetch呼び出しに渡します。

これにより、重要なイベントがトラップされ、コレクション ビューは各イベントを処理するために最小限の作業を行います。もちろん、この戦略はすべての状況に適用できるわけではありませんが、出発点としては良いと思います。

于 2012-11-27T08:01:04.090 に答える
3

さて、誰かがバインディングが機能しなかった理由を説明できるまで、私は次の回避策を使用しました:

   initialize: function () {
            var self = this;
            this.collection = new ProjectsCollection();
            this.collection.fetch({ success: function () { self.render(); } });

于 2012-11-27T07:35:56.890 に答える