Sub Class a Backbone.View Sub Class&保留事件

时间:2011-08-06 17:36:35

标签: javascript backbone.js underscore.js

我有一个Backbone.View的通用子类,它有一个close事件监听器。

var GenericView = Backbone.View.extend({

    events : {
        "click .close" : "close"
    },

    close : function () {
        console.log("closing view");
    }

});

我想继承这个泛型类并添加一些新事件。但是,下面将覆盖超类(上面)事件对象。 E.g。

var ImplementedView = new GenericView({

    // setting this will stop 'close' in Super Class from triggering
    events : {
        "click .submit" : "submit"
    }

}); 

我应该如何创建子类,在这种情况下ImplementedView并保留事件?

我找到了一种方法来实现这一点,通过在构造子类时扩展事件对象。但是我需要重新触发this.delegateEvents(),我猜这不好。任何人都可以对此发表评论吗?

var ImplementedView = new GenericView({

    initialize : function (options) {

        _.extend(this.events, {
            "click .submit" : "submit"
        });

        // re-attach events
        this.delegateEvents();
    }

});

5 个答案:

答案 0 :(得分:28)

@Nupul是完全正确的:你不是你的GenericView的子类。

事实上,子类化在这里并不是正确的词,因为JavaScript不进行经典继承。

所以让我们首先尝试理解这里发生的事情:

var GenericView = Backbone.View.extend( propertiesObj, classPropertiesObj )

Backbone.View是一个构造函数,在使用new关键字调用时,会为您创建一个新对象。

由于这是JS,所有函数都是函数对象,因此Backbone.View.extend只是一个挂起Backbone.View的函数,可以执行以下操作:

  1. 它设置原型链,因此您可以访问“基础”类
  2. 中定义的属性和调用函数
  3. 它创建并返回一个你可以调用的新构造函数(这里将是GenericView)来实例化你继承类的对象
  4. 它将自身复制为挂起它返回的构造函数的函数,以便您可以进一步继承。
  5. 因此,设置所需原型链的正确方法是:

    var ImplementedView = GenericView.extend({
      // implementation goes here
    });
    

    和NOT:

    var ImplementedView = new GenericView({//stuff});
    

    因为这只会创建一个GenericView的新实例。

    现在,您仍有问题,因为当您执行以下操作时:

    var impl_view = new ImplementedView;
    
    impl_view.events; // This isn't merged with the events you created
                      // for the GenericView
    

    此时有不同的方法可以获得您想要的结果,这里使用的delegateEvents类似于您的方式。顺便使用它也不错。

    var GenericView = Backbone.View.extend({
    
      genericEvents: { 'click .close': 'close' },
    
      close: function() { console.log('closing view...'); }
    
    });
    
    var ImplView = GenericView.extend({
    
      events: { 'click .submit': 'submit' },
    
      initialize: function(options) {
        // done like this so that genericEvents don't overwrite any events
        // we've defined here (in case they share the same key)
        this.events = _.extend({}, this.genericEvents, this.events);
        this.delegateEvents()
      }
    });
    

答案 1 :(得分:27)

另一种选择是让BaseView覆盖Extend的实现。如:

var BaseView = Backbone.View.extend({
        //base view functionality if needed
    });
BaseView.extend = function(child){
    var view = Backbone.View.extend.apply(this, arguments);
    view.prototype.events = _.extend({}, this.prototype.events, child.events);
    return view;
};

这会自动扩展您从BaseView继承的所有事件。

答案 2 :(得分:10)

我喜欢Shaver先生的解决方案,但是对于那些不那么具有侵入性的东西:

var ChildView = ParentView.extend({
    events : _.extend({
        "change input": "handleInputChange"
    }, ParentView.prototype.events)
});

编辑:是的,你必须在每个子类中执行此操作,但是当只需要几个孩子时,或者当你不控制父“class”时它会很有用。

答案 3 :(得分:3)

这是一个适合我的解决方案。您可以在父类和子类中使用events对象,而无需在每个子类中扩展它。只需在父类中扩展一次:

APP.Views.GenericWizard = Backbone.View.extend({
  events: {
    'click .btn-prev'   : function(){}
  },
  initialize: function() {
    _(this.events).extend(APP.Views.GenericWizard.prototype.events);
  }
});

APP.Views.RegisterWizard = APP.Views.GenericWizard.extend({
  events: {
    'blur #username' : function(){}
  },
});

var registerWizard = new APP.Views.RegisterWizard();
console.log(registerWizard.events);
// Object {blur #username: function, click .btn-prev: function}

答案 4 :(得分:1)

您可能会觉得这很有用:http://kalimotxocoding.blogspot.com/2011/03/playing-with-backbonejs-views.html

我提到的关于_.extend(...)以及你现在拥有的内容的几分之二......