5

ここで何かが完全に欠落している可能性がありますが、次のものがあります。

  • 「すべて」のデータをカプセル化するモデル (1 つの URL からロードされたすべての JSON)
  • モデルには、構築時に取得したデータでインスタンス化する 1 つ (または複数) のコレクションがあります
  • データが初期化されてロードされたときにコレクションで実行したいコード

私の質問は、構成されたコレクションについてです。コレクションの範囲外でこれを行うこともできますが、むしろカプセル化したいと思います(そうでなければ、イニシャライザなどを使用して「クラス」にするポイントは何ですか)。

  1. そのコードを関数に入れることができると思ってinitialize()いましたが、それはモデルが設定される前に実行されるため、コレクションを構成するモデルにアクセスできません (this.modelsは空です)。

  2. 次に、イベントにバインドできると思いましたが、初期化後にイベントがトリガーされません。Collection を独自のエンドポイントからロードした場合はそうなるでしょうが、fetch私はそうしていません。既存のデータからコレクションを初期化しています。

私の質問:データで初期化された直後にコレクションで実行する初期化コードを取得する方法 (つまりthis.models、空ではありません)。

「外部」コードを使用せずにこれを行うことは可能ですか?

これがデモコードです。おそらくこれでよりよく説明できます。

var Everything = Backbone.Model.extend({
    url: "/static/data/mydata.json",
    parse: function(data)
    {
        this.set("things", new Things(data.things, {controller: this}));
    }
});

var Thing = Backbone.Model.extend({
});

var Things = Backbone.Collection.extend({
  model: Thing,
  initialize: function(data, options)
  {
      // HERE I want access to this.models. 
      // Unfortunately it has not yet been populated.
      console.log("initialize");
      console.log(this.models);
      // result: []

      // And this event never gets triggered either!
      this.on("all", function(eventType)
      {
          console.log("Some kind of event happend!", eventType);
      });
  }
});

var everything = new Everything();
everything.fetch();

// Some manual poking to prove that the demo code above works:

// Run after everything has happened, to prove collection does get created with data
setTimeout(function(){console.log("outside data", everything.get("things").models);}, 1000);
// This has the expected result, prints a load of models.


// Prove that the event hander works.
setTimeout(function(){console.log("outside trigger", everything.get("things").trigger("change"));}, 1000);
// This triggers the event callback.
4

2 に答える 2

7

残念ながら、コレクションは最初に適切に初期化された後にのみデータで設定され、モデルはsilent: trueフラグを使用してリセットされます。これは、イベントがトリガーされないことを意味します。

本当に使いたい場合は、setTimeout(..., 0) またはアンダースコアdeferメソッドを使用して、やりたいことの実行を次のブラウザー イベント ループに遅らせることで、少しごまかすことができます。

initialize: function(data, options) {

     _.defer(_.bind(this.doSomething, this));
},

doSomething: function() {

    // now the models are going to be available
}
于 2012-02-04T01:56:18.127 に答える