主干自举集合未正确初始化 [英] Backbone bootstrapped collection doesn't initialize correctly

查看:11
本文介绍了主干自举集合未正确初始化的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个问题,真的很难注意到,因为在大多数情况下一切正常.只有当我尝试在我的集合初始化函数中操作我的数据时,我才发现问题.

主干文档位于 http://backbonejs.org/#Collection-constructor

如果你定义了一个初始化函数,它会在集合被创建的时候被调用."

所以我将其解释为,直到我的模型设置好后,我的初始化函数才会运行.这听起来很理想,"我说,但后来我遇到了这个问题.

我的引导代码如下:

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

我的收藏:

var MyCollection = Backbone.Collection.extend({模型:我的模型,初始化:函数(){控制台日志(这个);控制台日志(this.length);this.each(函数(模型){控制台日志(模型);});}});

我得到了奇怪的结果.

第一个 console.log(this); 是预期的集合对象:

<代码>{....型号:[3],长度:3....}

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

this.each() 中的控制台没有出现.

发生了什么?

解决方案

集合构造函数 看起来像这样:

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.modelsthis.length 你期望看到的.如果你说

console.log(this.toJSON());

或:

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

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

文档并没有明确说明在调用 initialize 时应该准备什么,因此您一直在跟踪源代码.这并不理想,但至少 Backbone 源是干净和直接的.

你会注意到 initialize 是这样调用的:

this.initialize.apply(this, arguments);

参数 在那里意味着 initialize 将接收与构造函数相同的参数,因此您可以根据需要查看那里:

初始化:函数(模型,选项){//原始模型数据将在 `models` 中所以做什么//需要完成.}

I have an issue, that was really hard to notice, because for the most part everything works. It was only when I tried to manipulate my data in my collections initialize function that I found a problem.

The backbone docs at http://backbonejs.org/#Collection-constructor

"If you define an initialize function, it will be invoked when the collection is created."

so I interpreted that as, my initialize function won't run until after my models are set. "That sounds ideal," said I, but then I ran into this.

My bootstrap code is as follows:

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

My collection:

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

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

I got strange results.

The first console.log(this); was a collection object as expected:

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

and the second console(this.length); printed out the number 0

the console inside this.each() didn't show up.

What's happening?

解决方案

The Collection constructor 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});
  //...
};

Step by step:

  1. The this._reset() call does a this.length = 0.
  2. The this.initialize.apply(...) is the call to your initialize method.
  3. The this.reset(...) will call add to add the models. The add call will update the collection's models and length properties.

So, when initialize is called, you'll have this.length == 0 and this.models will be an empty array since only _reset will have been called here. Now we can easily see why this.each doesn't do anything and why console.log(this.length) says 0.

But why does console.log(this) tell us that we have a populated collection? Well, console.log doesn't happen right away, it just grabs references to its arguments and logs something to the console a little bit later; by the time console.log gets around to putting something in the console, you'll have gotten through (3) above and that means that you'll have the this.models and this.length that you're expecting to see. If you say

console.log(this.toJSON());

or:

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

you'll see the state of things when console.log is called rather than the state of things when console.log writes to the console.

The documentation isn't exactly explicit about what is supposed to be ready when initialize is called so you're stuck tracing through the source. This isn't ideal but at least the Backbone source is clean and straight forward.

You'll notice that initialize is called like this:

this.initialize.apply(this, arguments);

The arguments in there means that initialize will receive the same arguments as the constructor so you could look in there if you wanted:

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

这篇关于主干自举集合未正确初始化的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆