2012-06-24 12 views
14

Prima di tutto, ho fatto qualche ricerca e nessuna risposta su StackOverflow/google mi ha fornito la cosa che volevo.Passare argomenti agli eventi in backbone

Ecco un frammento del mio codice:

//in the view 
this.collection.on("add",triggerthis) 
this.collection.add(predefinedModel) 
triggerthis: function(a, b, c, d){ 
    //etc. 
} 

Fondamentalmente, voglio essere in grado di passare un argomento su Add e ricevere l'argomento in triggerthis. È possibile?

Grazie in anticipo.

+1

Dal momento che il gestore triggerthis' 'evento sarà chiamato dal codice evento spina dorsale, dove si aspetta coloro argomento extra verrà da? –

+0

Scusa ma non sono sicuro di come funzioni. Suppongo di poter chiamare una funzione anonima in on() che chiama triggerthis all'interno, ma non sono sicuro se questo è il modo migliore per procedere. – chenglou

risposta

30

Non si può fare questo nel modo desiderato senza l'utilizzo di funzioni non documentate.

Se abbiamo uno sguardo a Collection#add, vedremo questo:

add: function(models, options) { 
    //... 
    for (i = 0, l = add.length; i < l; i++) { 
    (model = add[i]).trigger('add', model, this, options); 
    } 
    //... 
} 

Nota il quarto argomento a trigger. E se guardiamo l'interfaccia documentata per trigger:

grillettoobject.trigger(event, [*args])

callback innesco per la data dell'evento , o un elenco delimitato da spazi di eventi. Gli argomenti successivi al trigger verranno inoltrati ai callback dell'evento.

Così il add chiamerà gli ascoltatori come f(model, collection, options) dove options è lo stesso options quello che hai passato a Collection#add.Il risultato è che, se si esegue questa operazione:

this.collection.add(predefinedModel, { undocumented: 'arguments' }) 

allora si potrebbe fare questo nel vostro callback:

triggerthis: function(model, collection, options) { 
    console.log(options.undocumented); 
} 

Demo: http://jsfiddle.net/ambiguous/bqWwQ/

Si potrebbe naturalmente tunnel tutta una serie o un oggetto attraverso options in questo modo.

Il terzo argomento per "add" eventi non è documentato (almeno non che io riesco a trovare), la cosa più vicina alla documentazione per questo è una nota nella 0.3.3 Changelog entry:

Il options argomento onnipresente è ora passato come argomento finale a tutti gli eventi "change".

Non consiglierei questo approccio ma è lì se ne avete bisogno; Ovviamente dovrai copiarlo nella tua suite di test e dovrai assicurarti di non utilizzare alcuna chiave in options che verrà utilizzata da Backbone.


un approccio più sicuro sarebbe quello di collegare alcune proprietà in più per il modello:

model.baggage = { some: 'extra stuff }; 

e poi buccia che fuori nella richiamata:

triggerthis: function(model, collection) { 
    var baggage = model.baggage; 
    delete model.baggage; 
    //... 
} 

Demo: http://jsfiddle.net/ambiguous/M3UaH/

Puoi anche utilizzare diversi callback per scopi diversi o passare il tuo parametro aggiuntivo come attributi del modello in piena regola.

C'è anche _.bind:

this.collection.on("add", _.bind(function(collection, model, extra) { ... }, context, collection, model, 'whatever you want')); 

ma che legherà gli argomenti da sinistra a destra in modo da dovrete specificare tutti gli argomenti che il callback avrà bisogno.

Demo: http://jsfiddle.net/ambiguous/jUpJz/

+0

upvote - come la tecnica del bagaglio - funziona bene! grazie – sambomartin

6

Se i valori passati alla funzione sono sempre gli stessi, si può partially apply utilizzando _.bind (o il nativo Function.bind se disponibile)

Ad es Dove stai vincolante il gestore di add (supponendo triggerThis è un metodo nella vista):

this.collection.on('add', _.bind(this.triggerThis, this, a, b, c, d)); 

La definizione di triggerThis:

triggerThis: function(a, b, c, d /*, model, collection, options - if you need them*/) { 
    ... 
} 

Se si vuole passare gli argomenti a un individuo aggiungi chiamata, puoi utilizzare il secondo parametro options su add e gestirlo nel gestore eventi.

E.g.

this.collection.on('add', this.triggerThis, this); 
this.collection.add(model, { 
    someCustomValue: 'hello'; 
}); 

Poi, nel tuo gestore:

triggerThis: function(model, collection, options) { 
    var val = options.someCustomValue; 
    ... 
} 
+0

Il problema è che il terzo argomento 'options' non è esattamente documentato. –

+0

È vero, anche se in una delle voci del log delle modifiche (per 0.9.0) si dice che "All'interno degli eventi di aggiunta e rimozione di una raccolta, l'indice del modello che viene aggiunto o rimosso è ora disponibile come options.index." quindi presumo che probabilmente non andrà via presto. – jimr

+0

L'argomento 'options' per i callbacks è una sorta di area grigia, il tipo di documenti parla in giro senza venire fuori dicendo che è lì. Sospetto che a un certo punto verrà legittimato. Solo che valeva la pena ricordare che ci sono alcuni avvertimenti. –