骨干视图继承共享属性

Backbone View inheritance sharing properties

本文关键字:共享 属性 继承 视图      更新时间:2023-09-26

我正在扩展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,将其创建为实例变量,而不是将其附加到原型。

这是因为对原始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中初始化非共享属性。

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

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

希望这对你有帮助!

我对此写了一篇更详细的博客文章,但最简单的方法是提供一个自定义构造函数,以确保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"]