我正在使用 Hammer.js 在主干视图中捕获触摸屏事件。Hammer 有一个特殊的语法来添加触摸监听器,我一直在 View 的初始化函数中使用它:
$("#next-button").hammer({prevent_default: true}).on('tap', $.proxy(this.next, this));
我宁愿将它添加到标准事件对象中,如下所示:
events: {"tap #next-button":"next"}
所以我破解了 Backbone.View 的 delegateEvents 方法的结尾:
var isMobileEvent=["tap", "doubleTap"].indexOf(eventName)!=-1;
if (selector === '') {
if (isMobileEvent){
this.$el.hammer({prevent_default: true}).on(eventName, method);
} else {
this.$el.on(eventName, method);
}
} else {
if (isMobileEvent){
this.$el.hammer({prevent_default: true}).on(eventName, selector, method);
} else {
this.$el.on(eventName, selector, method);
}
}
这工作正常。但是当我试图在需要覆盖的一个视图中覆盖该方法时(担心我会忘记 Backbone 中的这个 hack,或者用新版本的 Backbone 覆盖它等),我的视图的 delegateEvents 停止工作. 问题是方法回调不被识别为方法:
if (!_.isFunction(method)) method = this[events[key]];
为什么?我从字面上将函数复制并粘贴到 View 子类中。这是在 Backbone 中工作的整个 delegateEvents,但不在我的 Backbone.View 中:
delegateEvents: function(events) {
if (!(events || (events = _.result(this, 'events')))) return;
this.undelegateEvents();
for (var key in events) {
var method = events[key];
if (!_.isFunction(method)) method = this[events[key]];
if (!method) throw new Error('Method "' + events[key] + '" does not exist');
var match = key.match(delegateEventSplitter);
var eventName = match[1], selector = match[2];
method = _.bind(method, this);
eventName += '.delegateEvents' + this.cid;
var isMobileEvent=["tap", "doubleTap"].indexOf(eventName)!=-1;
if (selector === '') {
if (isMobileEvent){
this.$el.hammer({prevent_default: true}).on(eventName, method);
} else {
this.$el.on(eventName, method);
}
} else {
if (isMobileEvent){
this.$el.hammer({prevent_default: true}).on(eventName, selector, method);
} else {
this.$el.on(eventName, selector, method);
}
}
}
修复:
替换这一行:
var match = key.match(delegateEventSplitter);
有了这个:
var match = key.match(/^(\S+)\s*(.*)$/);