重写继承的Backbone.js视图的事件哈希



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

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

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

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

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

事实上,Backbone.js文档中已经提出了这种方法。

我利用Backbone.js文档中提到的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,依此类推

您确实需要以以下特定方式设置this.events

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

而不是

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

以第二种方式进行操作将在父对象(ElementView)原型中生成事件对象。第一种方法确保每个模型都有自己的副本。

最新更新