我有一个通用元素的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
)原型中生成事件对象。第一种方法确保每个模型都有自己的副本。