骨干和listenTo和一个奇怪的边界效果

时间:2013-02-11 10:08:46

标签: javascript backbone.js

我定义了骨干视图

Views.BaseView = Backbone.View.extend({
   viewState : new Backbone.Model(),
   initialize: function(){
       this.listenTo(this.viewState, "change:stateType", this.onAlertType)
  }
}

我有扩展BaseView的GlobalView,这允许我显示和管理我的ItemViews。 ItemView也扩展了BaseView。

我的问题是,如果我在ItemView级别更改viewState.stateType:

MyItemView.viewState.set('stateType', 1)

首先通知GlobalView有关ItemView的viewState属性的更改。

我的GlobalView没有得到任何特定的'listenTo',我定义的唯一'listenTo'是BaseView级别的那个。

为什么要通知globalView有关ItemView上viewState对象的更改? 有人看到我做错了吗?这是一个已知的错误吗?

1 个答案:

答案 0 :(得分:1)

使用View在Backbone对象(例如.extend)上定义属性时,该属性将附加到对象的原型。这意味着该对象的所有实例共享相同的属性值。

这对方法非常有意义,因为您不希望为对象的每个实例的每个方法创建一个新的函数实例。它对不可变值类型属性也相对无害,因为原始值未被修改,并且当您使用另一个值重新分配属性时,会在该实例上创建一个新属性,并隐藏原型属性而不修改它:

var SomeView = BaseView.extend({
  foo:'foo'
});

var view1 = new SomeView();
var view2 = new SomeView();

view1.foo = 'bar';
console.log(view1.foo, view2.foo); // -> bar, foo

当您将属性设置为可变对象(例如ObjectArray或类似对象)时,会出现问题。如果在不重新分配属性的情况下更改该对象,则会更改所有实例上的该属性值。

在您的情况下,所有视图的viewState属性都指向同一个模型实例,因此:

var view1 = new SomeViewThatExtendsBaseView();
view1.viewState.set('stateType', 1);

var view2 = new SomeOtherViewThatAlsoExtendsBaseView();
console.log(view2.viewState.get('stateType')); // -> 1

要使用Backbone声明实例属性,您应该使用initialize方法创建它们:

Views.BaseView = Backbone.View.extend({
  initialize: function() {
    this.viewState = new Backbone.Model();
    this.listenTo(this.viewState, "change:stateType", this.onAlertType)
  }
}