25

次のように、ハンドラーをバックボーンビューにアタッチできます。

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 }

しかし、これは理想的ではないようです...

4

2 に答える 2

36

これ:

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

eventsはオブジェクトリテラルであり、オブジェクトには最大で1つの(キー、値)ペアを含めることができるため、は機能しません。それはおそらく言うことと同じでしょう:

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

このCoffeeScript:

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

JavaScriptバージョンと機能的に同じであり、同じ理由で機能しません。

アンディレイの使用のアイデア

'event selector': 'callback1 callback2'`

バックボーンは空白の値を分割する必要があることを理解しないため、どちらも機能しません。同様に、これ:

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

バックボーンはこのコンテキストで配列をどう処理するかを知らないため、機能しません。

ビューはイベントをバインドし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' ]

バックボーンにパッチを適用したり、そのようなパッチをバックボーンメンテナに転送したりしたくない場合は、元の「手動ディスパッチ」のアイデアを使用できます。

'event selector': 'dispatcher'
//...
dispatcher: function(ev) {
    this.handler1(ev);
    this.handler2(ev);
}
于 2012-06-06T15:46:35.540 に答える
9

jQueryのイベント名前空間を使用してこの問題を解決しました

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

これは、イベント名前空間が本来意図されていたものではありませんが、他の名前空間と衝突しない限り、問題を引き起こすことはありません。

主な問題は、オブジェクトのキーごとに1つの値しか持てないことです。これにより、キーが一意になります。

于 2013-04-28T18:13:52.250 に答える