子类a Backbone.View子类和保留事件

Ros*_*oss 21 javascript backbone.js underscore.js

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

var GenericView = Backbone.View.extend({

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

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

});
Run Code Online (Sandbox Code Playgroud)

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

var ImplementedView = new GenericView({

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

}); 
Run Code Online (Sandbox Code Playgroud)

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

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

var ImplementedView = new GenericView({

    initialize : function (options) {

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

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

});
Run Code Online (Sandbox Code Playgroud)

sat*_*run 28

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

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

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

var GenericView = Backbone.View.extend( propertiesObj, classPropertiesObj )
Run Code Online (Sandbox Code Playgroud)

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

由于这是JS,所有函数都是函数对象,所以Backbone.View.extend只是一个挂起的函数Backbone.View做了一些事情:

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

因此,设置所需原型链的正确方法是:

var ImplementedView = GenericView.extend({
  // implementation goes here
});
Run Code Online (Sandbox Code Playgroud)

并不是:

var ImplementedView = new GenericView({//stuff});
Run Code Online (Sandbox Code Playgroud)

因为这只是创建一个GenericView的新实例.

现在,你仍然有一个问题,因为你做的事情如下:

var impl_view = new ImplementedView;

impl_view.events; // This isn't merged with the events you created
                  // for the GenericView
Run Code Online (Sandbox Code Playgroud)

在这一点上,有不同的方法来获得你想要的结果,这是一个使用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()
  }
});
Run Code Online (Sandbox Code Playgroud)

  • 这是一个很好的答案.虽然缺点是必须粘贴:`this.events = _.extend(this.genericEvents,this.events);`在每个子视图的init中.但我想我可以处理.希望有更自动的方式. (2认同)
  • @JoeLongstreet注意this.events的赋值.正如评论所解释的那样,我们不希望覆盖我们的子类的事件.它应该是`this.events = _.extend({},this.genericEvents,this.events);`,因为我们真的不想改变genericEvents对象.我编辑了帖子以反映这一点. (2认同)

Wil*_*ver 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;
};
Run Code Online (Sandbox Code Playgroud)

这将自动扩展您从BaseView继承的所有事件.


Pet*_*eng 10

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

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

编辑:是的,您必须在每个子类中执行此操作,但是当只需要几个子项时,或者当您不控制父"类"时,它很有用.