2012-09-22 10 views
6

ほとんどの場合、すべてが機能するので、それは気づくのが難しい問題があります。私が問題を見つけたコレクションの初期化関数で自分のデータを操作しようとしたときだけでした。 http://backbonejs.org/#Collection-constructorバックボーンのブートストラップされたコレクションが正しく初期化されない

バックボーンドキュメントは、「あなたは初期化関数を定義した場合、コレクションが作成されたとき、それが呼び出されます。」

私はモデルを設定するまで、私の初期化関数は実行されないと解釈しました。 「それは理想的ですね」と私は言ったが、その後私はこれに遭遇した。次のように

私のブートストラップコードは次のとおりです。

new MyCollection(<?php if ($data) {echo json_encode($data);} ?>); 

マイコレクション:私は奇妙な結果を得た

var MyCollection = Backbone.Collection.extend({ 
    model: MyModel, 

    initialize: function() { 
     console.log(this); 
     console.log(this.length); 
     this.each(function(model) { 
      console.log(model); 
     }); 
    } 
}); 

最初console.log(this);は予想通りコレクションオブジェクトであった:

{ 
    .... 
    models: [3], 
    length: 3 
    .... 
} 

this.each()内側第console(this.length);プリントアウト数0

コンソールが表示されませんでした。

何が起こっているか

+0

新しいMyCollection( <?php if($ data){echo json_encode($ data);}?>); < - yuck –

答えて

11

コレクションコンストラクタlooks like this:ステップバイ

var Collection = Backbone.Collection = function(models, options) { 
    //... 
    this._reset(); 
    this.initialize.apply(this, arguments); 
    //... 
    this.reset(models, {silent: true, parse: options.parse}); 
    //... 
}; 

ステップ:

  1. this._reset()呼び出しがthis.length = 0を行います。
  2. this.initialize.apply(...)は、initializeメソッドへの呼び出しです。
  3. this.reset(...)addと呼び出してモデルを追加します。 addコールでは、コレクションのmodelslengthのプロパティが更新されます。

ので、initializeが呼び出されたとき、あなたはthis.length == 0を持っているだろうとだけ_resetがここに呼ばれていますので、this.modelsは空の配列になります。今度はなぜthis.eachが何もしない理由となぜconsole.log(this.length)0と表示されるのかを簡単に見ることができます。

しかし、なぜconsole.log(this)に人口集めがあるのですか?さて、console.logはすぐには起こりません。ちょうどその引数への参照を取得し、ちょっと後にコンソールに何かを記録します。 console.logがコンソールに何かを入れようとすると、上記の(3)が表示され、あなたが見ると予想しているのはthis.modelsthis.lengthです。あなたは

console.log(this.toJSON()); 

かを言う場合:

console.log(_(this.models).clone()) 

あなたはconsole.logは、コンソールに書き込むときconsole.logは、物事の状態ではなく、呼ばれているものの状態が表示されます。

ドキュメントでは、ソースによってトレース立ち往生しているようinitializeが呼び出されたときに準備することになっているかについて、正確に明示的ではありません。これは理想的ではありませんが、少なくともバックボーンのソースはきれいで簡単です。

あなたはinitializeがこのように呼び出されることがわかります:

this.initialize.apply(this, arguments); 

そこにargumentsは、あなたが望んでいた場合は、そこに見ることができるようinitializeはコンストラクタと同じ引数を受け取ることを意味します

initialize: function(models, options) { 
    // The raw model data will be in `models` so do what 
    // needs to be done. 
} 
+0

非常に徹底的な説明をありがとう。今、 'reset'が私の初期化の後に呼び出され、それがなぜ起こっているのかを説明していますが、私はまだ私のモデルにアクセスする方法を知る必要があります。 'each'コールのものにアクセスするには、事前に「リセット」イベントを聞く必要がありますか? 'this.on( "リセット"、this.doSomeStuff);' – nackjicholson

+0

あなたの編集には、それをクリアしました。どうもありがとうございました。しかし、私は 'this.each()'内のコンソールが正しく動作するとはまだ考えていません。それはちょうどだから右、 'まだ何もしませんthis.collection.each':' – nackjicholson

+1

@eO_Ae;私は(モデル、機能(モデル){// ...}) '_.eachを行う必要があるでしょう'_(this.collection.models).each(...)'のラッパーです。 '_(models).each(...) 'の' model'はモデルオブジェクトではありません。 –

1

あなたは間違ってブートストラップされています。あなたは、ブートストラップコード

ので

のようなコレクションのリセット()メソッドを使用する必要があり、あなたのcollectonでリセットイベントをリッスンします:

var collection = new MyCollection; 
collection.reset(<?php if ($data) { echo json_encode($data); } ?>); 

あなたのコレクションコード:

var MyCollection = Backbone.Collection.extend({ 
    model: MyModel, 

    initialize: function() { 
     this.on("reset", this.foobar); 
    }, 

    foobar: function(collection) { 
     console.log(this); // will be the same 
     console.log(this.length); // will equal 3 
     this.each(function(model) { 
      console.log(model); // will output a console for each model. 
     }); 
    } 

}); 
+0

これは多くのことを助け、そして私は、これは、バックボーンのFAQによるとブートストラップの推奨方法であることがわかります。 http://backbonejs.org/#FAQ-bootstrap – nackjicholson

関連する問題