2012-06-06 15 views
25

posso collegare i gestori di Backbone Visualizzazioni come:Come posso associare 2 gestori allo stesso evento?

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

Ma cosa succede se voglio collegare più di 1 gestore per lo stesso evento?

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

ho potuto creare un gestore personalizzato come

Ma questo non sembra l'ideale ...

+0

Sono disposto a scommettere "xxx": "eventHandler1 eventHandler2" funziona, testando ora –

+1

@AndyRay: quanto vuoi scommettere? https://github.com/documentcloud/backbone/blob/master/backbone.js#L1242 –

+0

@muistooshort, quindi posso dire che il metodo che dovrei usare ora è: '" eventname ": function (e) {handler1 (e); handler2 (e)} '? – jm2

risposta

36

questo:

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

non funzionerà perché events è un oggetto letterale e puoi avere al massimo una coppia (chiave, valore) in un oggetto. Che probabilmente sarebbe lo stesso che dire:

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

Questo CoffeeScript:

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

è funzionalmente identico alla versione JavaScript e non funzionerà per lo stesso motivo. L'idea di

Andy Ray di usare

'event selector': 'callback1 callback2'` 

non funzionerà sia come Backbone non capirà che dovrebbe dividere il valore di spaziatura; Allo stesso modo, questo:

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

non funzionerà perché Backbone non sa cosa fare con una matrice in questo contesto.

Visualizzazioni legano i loro eventi attraverso delegateEvents e che assomiglia a questo:

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... 
    } 
} 

Così method inizia come il valore per 'event selector'.Se si tratta di una funzione da qualcosa come:

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

allora è usato così com'è, altrimenti viene convertito in una proprietà di this:

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

Se si dovesse grassetto, si potrebbe regolare delegateEvents per capire un array o spazi bianchi stringa delimitata:

// 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... 
} 

un abbastanza semplice patch del genere permetterebbe di utilizzare uno spazio bianco elenco delimitato dei gestori:

'event selector': 'callback1 callback2' 

o un array di gestori:

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

o anche una serie mista di nomi dei metodi e funzioni:

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

Se non si desidera applicare la patch al Backbone o in avanti una tale patch per i manutentori Backbone allora si potrebbe andare con la tua idea originale di "dispacciamento manuale":

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

+1 una buona risposta completa –

9

Ho risolto questo problema utilizzando jQuery's event namespaces

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

Questo non è ciò che gli spazi dei nomi evento sono stati originariamente previsto per, ma fintanto che non si scontrano con altri spazi dei nomi non dovrebbe causare un problema.

Il problema principale è che è possibile avere un solo valore per chiave in un oggetto e questo rende le chiavi univoche.

+0

Bella. Ho finito per fare questo: 'eventi: { 'click.first a': 'hideAll', 'click.second a': 'showContent' }' – eightyfive

Problemi correlati