Backbone View继承共享属性

时间:2013-04-12 09:34:07

标签: javascript backbone.js

我正在扩展Backbone视图,如:

var baseView = Backbone.View.extend({
    fruits : [],
    listFruits : function() {
        console.log(this.fruits);
    }
});

var firstView = baseView.extend({
    initialize : function() {
        this.fruits.push("apple");
    }
});

var secondView = baseView.extend({
    initialize : function() {
        this.fruits.push("pear");
    }
});


var firstViewInstance = new firstView(); // ["apple", "pear"]
var secondViewInstance = new secondView(); // ["apple", "pear"]

firstViewInstance.listFruits();
secondViewInstance.listFruits();

在我看来,firstViewInstancesecondViewInstance应该是完全分开的,但它们显然是相关的。如何实现两个单独的视图对象,既继承自公共基础,又共享数据?

编辑: 基于下面的答案,我在http://jsfiddle.net/qZ7SU/处有一个更新的小提琴,似乎可以解决这个问题。我仍然不完全清楚发生了什么,但我认为明确地将fruits[]附加到this,将其创建为实例变量,而不是将其附加到原型。

2 个答案:

答案 0 :(得分:4)

这是因为对原始fruits - 属性的引用是被复制到子视图的属性。见underscore.js extend

_.extend = function(obj) {
  each(slice.call(arguments, 1), function(source) {
    if (source) {
      for (var prop in source) {
        obj[prop] = source[prop];
      }
    }
  });
  return obj;
};

要从公共基础继承但不共享数据,您需要初始化initialize-function中的not-shared属性。

var baseView = Backbone.View.extend({
  initialize: function() {
    this._initializeBase();
  },

  _initializeBase: function() {
    this.fruits = [];
  },

  listFruits : function() {
    console.log(this.fruits);
  }
});

var firstView = baseView.extend({
  initialize : function() {
    this._initializeBase();
    this.fruits.push("apple");
  }
});

这样,属性将在初始化时添加到对象中,并且不会共享数据。

希望这有帮助!

答案 1 :(得分:2)

我写了一篇关于此问题的更详细的blog post,但最简单的方法是提供一个自定义构造函数,确保在每个子视图的原型上创建fruits,而不是baseView.prototype所有子视图都继承。

var baseView = Backbone.View.extend({
  constructor: function() {
    this.fruits = [];
    Backbone.View.apply(this, arguments);
  },
  listFruits : function() {
    console.log(this.fruits);
  }
});

var firstView = baseView.extend({
    initialize : function() {
        this.fruits.push("apple");
    }
});

var secondView = baseView.extend({
    initialize : function() {
        this.fruits.push("pear");
    }
});


var firstViewInstance = new firstView(); // ["apple"]
var secondViewInstance = new secondView(); // ["pear"]