覆盖继承的Backbone.js视图的事件哈希

时间:2012-01-26 01:15:02

标签: javascript backbone.js

我有一个Backbone View,用于表示特定元素将继承的一般元素。我有需要应用于所有元素的事件处理逻辑,以及特定于子类型元素的事件处理逻辑。我遇到了麻烦,因为子View有一个也由父View处理的事件的回调,因此当我尝试在两者中使用事件哈希时,永远不会调用子回调或父回调。让我用一些代码来说明:

var ElementView = Backbone.View.extend({
  events: {
    "mouseup": "upHandler",
    "mousedown": "downHandler",
    "mousemove": "moveHandler"
  },

  initialize: function() {
    // add events from child
    if (this.events)
      this.events = _.defaults(this.events, ElementView.prototype.events);

    this.delegateEvents(this.events);
  }
});

var StrokeView = ElementView.extend({
  events: {
    "mousemove": "strokeMoveHandler"
  }
});

我如何以可扩展的方式解决这个问题,特别是如果我以后会有另一个级别的继承?

2 个答案:

答案 0 :(得分:8)

处理此问题的一种方法是对事件使用“名称空间”:

var ElementView = Backbone.View.extend({
  events: {
    "mouseup.element": "upHandler",
    "mousedown.element": "downHandler",
    "mousemove.element": "moveHandler"
  },

  initialize: function() {
    // add events from child
    if (this.events)
      this.events = _.defaults(this.events, ElementView.prototype.events);

    this.delegateEvents(this.events);
  }
});

var StrokeView = ElementView.extend({
  events: {
    "mousemove.strokeview": "strokeMoveHandler"
  }
});

事实上,这种方法是suggested in Backbone.js documentation

答案 1 :(得分:4)

我已经做了类似的事情,利用了Backbone.js documentation中提到的JavaScript的虚假super和初始化函数

var ElementView = Backbone.View.extend({
  events: {
    "mouseup": "upHandler",
    "mousedown": "downHandler",
    "mousemove": "moveHandler"
  },

  initialize: function() {
    this.delegateEvents();
  }
});

var StrokeView = ElementView.extend({
  initialize: function() {
    this.events = _.extend({}, this.events, {
      "mousemove": "strokeMoveHandler"
    });

    // Call the parent's initialization function
    ElementView.prototype.initialize.call(this);
  }
});

var SubStrokeView = StrokeView.extend({
  initialize: function() {
    this.events = _.extend({}, this.events, {
      "click": "subStrokeClickHandler",
      "mouseup": "subStrokeMouseupHandler"
    });

    // Call the parent's initialization function
    StrokeView.prototype.initialize.call(this);
  }
});

var c = new SubStrokeView();
console.log(c.events);

// Should be something like
// click: "subStrokeClickHandler"
// mousedown: "downHandler"
// mousemove: "strokeMoveHandler"
// mouseup: "subStrokeMouseupHandler"

通过在initialize函数中设置事件来实现神奇。如果您的原型中有多个events属性,那么由于原型设计的工作原理,JavaScript只能看到最近的属性。

相反,通过这种方式,每个视图都设置自己的this.events,然后调用其父级initialize函数,后者又将this.events与其事件一起扩展,依此类推。 / p>

您需要以这种特定方式设置this.events

this.events = _.extend({}, this.events, ...new events...);

而不是

_.extend(this.events, ...new events...);

以第二种方式执行此操作将使父事件(ElementView)原型中的事件对象变得清晰。第一种方法确保每个模型都有自己的副本。