为什么我的视图在Backbone中的数组长度不正确?

时间:2012-06-04 17:57:07

标签: javascript jquery backbone.js

我有3个视图,ViewA包含一组ViewB子视图,每个ViewB包含一组ViewC子视图。

ViewA: Backbone.View.extend({
  viewBChildren: [],
  initialize: function() {
    // Do stuff
    var self = this;
    // Generate children
    this.model.get("CollectionB").each(function(b) {
      var viewB = new ViewB({
        // set properties
      });
      self.viewBChildren.push(viewB);
      console.log(self.viewBChildren.length); // Prints out correctly
    });
  }
});

ViewB: Backbone.View.extend({
  viewCChildren: [],
  initialize: function() {
    var self = this;
    this.model.get("CollectionC").each(function (c) {
      var viewC = new ViewC({
        // Set properties      
      });
      self.viewCChildren.push(viewC);
      console.log(self.viewCChildren.length); // Prints out a running total
    });
  }
});

因此,如果我在CollectionB中有5个项目,我希望viewBChildren.length也是5.这是真的并且工作正常。

我的问题是打印出viewCChildren.length时。如果CollectionB中的每个项目有5个孩子,我希望它打印出5五次。相反,它打印出一个运行总计,5,10,15,20,25。

没有其他代码会触及这些子集合,也没有其他方法可以修改它。我的视图初始化方法中的两个调用是影响集合的唯一方法。

我觉得我有一个范围问题,但我看不出我做错了什么。有什么想法吗?

1 个答案:

答案 0 :(得分:4)

您在视图中定义的属性:

var V = Backbone.View.extend({
    p: [ ],
    ...
});

未被深度复制到实例,它们会附加到V的原型,因此会在V及其所有实例之间共享。

考虑到这一点,我们可以看到发生了什么。每次这样做:

self.viewCChildren.push(viewC);

你实际上正在做ViewB.prototype.viewCChildren.push(viewC),这就是为什么你得到一个总计。

例如,如果我们这样做(http://jsfiddle.net/ambiguous/Z3QC6/):

var V = Backbone.View.extend({
    a: [ ],
    initialize: function() {
        this.a.push('pancakes');
    }
});

// The setTimeouts are to kludge around the asynchronous nature
// of some console.logs. Play with the times if you're seeing
// two element arrays for all the console.log calls.
var v1, v2;
console.log(V.prototype.a);
setTimeout(function() {
    v1 = new V();
    console.log(v1.a);
    console.log(V.prototype.a);
}, 100);
setTimeout(function() {
    v2 = new V();
    console.log(v1.a);
    console.log(v2.a);
    console.log(V.prototype.a);
}, 500);

然后我们将在控制台中得到它:

[]
["pancakes"]
["pancakes"]
["pancakes", "pancakes"]
["pancakes", "pancakes"]
["pancakes", "pancakes"]

而不是

[]
["pancakes"]
[]
["pancakes"]
["pancakes"]
[]

你可能在期待。

如果要将数组用作视图实例属性,则应在initialize中进行设置:

initialize: function() {
    this.viewCChildren = [ ];
}

例如,这个(http://jsfiddle.net/ambiguous/BjCvf/):

var V = Backbone.View.extend({
    a: [ ],
    initialize: function() {
        this.a = [ ];
        this.a.push('pancakes');
    }
});
// The rest as above

将生成此控制台输出:

[]
["pancakes"]
[]
["pancakes"]
["pancakes"]
[]