Backbone.js查看继承

时间:2011-10-12 04:02:56

标签: inheritance backbone.js

我有一个名为Pannel的视图,它只是一个带有关闭按钮的背景。我想将该视图扩展为名为PannelAdvanced的视图。我怎么能用backbone.js做到这一点?

现在所有示例都有Backbone.View.Extend,但这些示例只是扩展Backbone.View;我想扩展我的PannelView

3 个答案:

答案 0 :(得分:100)

继承视图的最简单方法是执行其他人已在评论中建议的内容:

var Pannel = Backbone.View.extend({
});

var PannelAdvanced = Pannel.extend({
});

但是就像你在评论中提到的那样,如果你在Pannel中有一个初始化方法,那么如果你在PannelAdvanced中也有一个初始化方法就不会被调用,所以你必须明确地调用Pannel的初始化方法: / p>

var Pannel = Backbone.View.extend({
   initialize: function(options){
      console.log('Pannel initialized');
      this.foo = 'bar';
   }
});

var PannelAdvanced = Pannel.extend({
   initialize: function(options){
      Pannel.prototype.initialize.apply(this, [options])
      console.log('PannelAdvanced initialized');
      console.log(this.foo); // Log: bar
   }
});

这有点难看,因为如果你有很多从Pannel继承的视图,那么你将不得不记得从所有这些视图中调用Pannel的初始化。更糟糕的是,如果Pannel现在没有初始化方法但你选择在将来添加它,那么你将来需要去所有继承的类并确保它们调用Pannel的初始化。所以这里是另一种定义Pannel的方法,这样你的继承视图就不需要调用Pannel的初始化方法了:

var Pannel = function (options) {

    // put all of Panel's initialization code here
    console.log('Pannel initialized');
    this.foo = 'bar';

    Backbone.View.apply(this, [options]);
};

_.extend(Pannel.prototype, Backbone.View.prototype, {

    // put all of Panel's methods here. For example:
    sayHi: function () {
        console.log('hello from Pannel');
    }
});

Pannel.extend = Backbone.View.extend;


// other classes inherit from Panel like this:
var PannelAdvanced = Pannel.extend({

    initialize: function (options) {
        console.log('PannelAdvanced initialized');
        console.log(this.foo);
    }
});

var pannelAdvanced = new PannelAdvanced(); //Log: Pannel initialized, PannelAdvanced initialized, bar
pannelAdvanced.sayHi(); // Log: hello from Pannel

答案 1 :(得分:29)

这是我喜欢使用Coffeescript的原因之一。像继承这样的事情要好得多。为了捎带@ JohnnyO的正确答案,我可以在Coffeescript中说同样的事情:

class Panel extends Backbone.View
    initialize: ->
        console.log 'Panel initialized'
        @foo = 'bar'

class PanelAdvanced extends Panel
    initialize: ->
        super
        console.log 'PanelAdvanced initialized'
        console.log @foo

答案 2 :(得分:8)

进一步捎带:

我喜欢@JohnnyO的方法但是想确认一个结果视图仍然能够做它应该做的一切。鉴于他的方法,我没有怀疑会有任何问题,但我想更加确定。

所以,我花了一分钟时间将Backbone.js Views test suite改编为@JohnnyO提出的多重继承技术。

您可以在http://jsfiddle.net/dimadima/nPWuG/处运行结果。 所有测试都通过。

我的基础和扩展视图:

var RegularView = function (options) {
  // All of this code is common to both a `RegularView` and `SuperView`
  // being constructed.
  this.color = options && (options.color || 'Green');

  // If execution arrives here from the construction of
  // a `SuperView`, `Backbone.View` will call `initialize`
  // that belongs to `SuperView`. This happens because here
  // `this` is `SuperView`, and `Backbone.View`, applied with
  // the current `this` calls `this.initialize.apply(this, arguments)`
  Backbone.View.apply(this, arguments)
};

RegularView.extend = Backbone.View.extend;

_.extend(RegularView.prototype, Backbone.View.prototype, {
  // Called if a `RegularView` is constructed`,
  // Not called if a `SuperView` is constructed.
  initialize: function () {
    console.log('RegularView initialized.');
  },

  say_hi: function() {
    console.log('Regular hi!');
  }

});

var SuperView = RegularView.extend({
  // Called if a `SuperView` is constructed`,
  // Not called if a `RegularView` is constructed.
  initialize: function(options) {
    console.log('SuperView initialized.')
  },

  say_hi: function() {
    console.log('Super hi!');
  }
})

对于测试套件,我抓住了latest views tests from GitHub并用Backbone.View替换了RegularView的出现次数。然后测试使用RegularViewRegularView.extend()的结果来确保两者都做他们应该做的事。