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 
    .... 
} 

第二个console(this.length);打印出数字0

里面的控制台this.each()没有出现。

发生了什么?

4

2 回答 2

11

Collection 构造函数如下所示

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并且this.models将是一个空数组,因为只有_reset在这里被调用。现在我们可以很容易地看到为什么this.each不做任何事情和为什么console.log(this.length)0

但是为什么console.log(this)告诉我们我们有一个填充的集合?好吧,console.log它不会立即发生,它只是获取对其参数的引用并稍后将某些内容记录到控制台;等到可以在控制台中放一些东西的时候console.log,你已经通过了上面的(3)this.models,这意味着你将拥有this.length你期望看到的东西。如果你说

console.log(this.toJSON());

或者:

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

您将看到console.log被调用时的状态,而不是console.log写入控制台时的状态。

该文档并未完全明确说明在调用时应该准备什么initialize,因此您无法通过源进行跟踪。这并不理想,但至少 Backbone 源是干净且直截了当的。

你会注意到它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.
}
于 2012-09-22T02:38:05.953 回答
1

您的引导不正确。您将需要使用 Collection reset() 方法,并像这样在您的收藏中侦听重置事件

引导代码:

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.
       });
    }

});
于 2012-09-22T05:07:49.880 回答