如何将2个处理程序附加到同一事件?

时间:2012-06-06 06:57:13

标签: javascript backbone.js backbone-events backbone-views

我可以将处理程序附加到Backbone Views,如:

var TodoView = Backbone.View.extend({
    events: {
        "xxx": "eventHandler1"
        "yyy": "eventHandler2"
    }
});

但是如果我想在同一个事件中附加多个处理程序呢?

var TodoView = Backbone.View.extend({
    events: {
        "xxx": "eventHandler1"
        "yyy": "eventHandler2"
        "xxx": "eventHandler3" // this isn't valid ... at least in CoffeeScript
    }
});

我可以创建一个像

这样的自定义处理程序
function compositeXXX() { eventHandler1(); eventHandler2 }

但这似乎并不理想......

2 个答案:

答案 0 :(得分:36)

此:

events: {
    "xxx": "eventHandler1",
    "yyy": "eventHandler2",
    "xxx": "eventHandler3"
}

将无效,因为events是一个对象文字,并且对象中最多只能有一个(键,值)对。这可能与说:

相同
events: {
    "xxx": "eventHandler3",
    "yyy": "eventHandler2"
}

这个CoffeeScript:

events:
    "xxx": "eventHandler1"
    "yyy": "eventHandler2"
    "xxx": "eventHandler3"

在功能上与JavaScript版本完全相同,但出于同样的原因不起作用。

Andy Ray使用

的想法
'event selector': 'callback1 callback2'`

不会工作,因为Backbone不会理解它应该在空格上拆分值;同样地,这个:

'event selector': [ 'callback1', 'callback2' ]

不起作用,因为Backbone在这种情况下不知道如何处理数组。

视图通过delegateEvents绑定他们的事件,看起来像这样:

delegateEvents: function(events) {
  // Some preamble that doesn't concern us here...
  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');
    // And some binding details that are of no concern either...
  }
}

因此method'event selector'的值开头。如果它是一个类似的函数:

'event selector': function() { ... }

然后按原样使用,否则将其转换为this

的属性
method = this[events[key]]; // i.e. method = this[method]

如果一个是粗体,可以调整delegateEvents以理解数组或空格分隔的字符串:

// Untested code.
var methods = [ ];
if (_.isArray(method))
  methods = method;
else if (_.isFunction(method))
  methods = [ method ];
else
  methods = method.split(/\s+/);
for (var i = 0; i < methods.length; ++i) {
  method = methods[i];
  if (!_.isFunction(method))
    method = this[method];
  // And the rest of the binding stuff as it is now with a possible adjustment
  // to the "method does not exist" exception message...
}

这样一个相当简单的补丁允许你使用以空格分隔的处理程序列表:

'event selector': 'callback1 callback2'

或一组处理程序:

'event selector': [ 'callback1', 'callback2' ]

甚至是方法名称和函数的混合数组:

'event selector': [ 'callback_name1', function() { ... }, 'callback_name2' ]

如果您不想修补Backbone或将此类补丁转发给Backbone维护人员,那么您可以使用原始的“手动调度”理念:

'event selector': 'dispatcher'
//...
dispatcher: function(ev) {
    this.handler1(ev);
    this.handler2(ev);
}

答案 1 :(得分:9)

我使用jQuery's event namespaces

解决了这个问题
var TodoView = Backbone.View.extend({
    events: {
        "xxx.handler1": "eventHandler1",
        "yyy": "eventHandler2",
        "xxx.handler3": "eventHandler3"
    }
});

这不是最初用于命名空间的事件名称空间,但只要它们不与其他名称空间冲突就不应该导致问题。

主要问题是,对象中每个键只能有一个值,这使得键唯一。