2012-07-31 13 views
10

Sto tentando di specificare un effetto di ingresso sugli elementi che vengono inseriti utilizzando un binding foreach knockoutjs. Molto semplice configurazione:knockoutjs afterRender function in foreach binding

myViewModel.myObservableArray.push({enter:function() { ... }); 

e nella marcatura:

foreach:{data:myObservableArray, afterRender:enter} 

sembra come dovrebbe funzionare ... giusto? Ma non trova la funzione di invio sull'elemento. Quello che ho trovato funziona è:

myViewModel.enter = function(something, item) { item.enter(); }; 

foreach:{data:myObservableArray, afterRender:$root.enter} 

l'aggiunta di una funzione di immettere alla vista del modello principale e vincolante afterRender a $ root.enter. Enter viene quindi passato l'elemento come secondo parametro, quindi a sua volta può chiamare la funzione di inserimento dell'oggetto, ma sembra un trucco.

Qualcuno può spiegare cosa sta succedendo qui?

Grazie.

EDIT:

Per chiarire Ho creato un fiddle.

Ciò che fa è molto semplice, ed è coperto in modo più approfondito nel animated transitions example. Sta eseguendo una funzione nel modello di visualizzazione radice per ciascun elemento dom inserito utilizzando l'associazione foreach.

Quindi la domanda è: cosa succede se desidero le funzioni afterRender, afterAdd o beforeRemove specifiche dell'oggetto? Potrei vedere questo essere utile. Soprattutto se si utilizza l'associazione del modello per selezionare dinamicamente un modello (note 4). C'è un modo pulito per farlo? In questo momento ho una funzione enter nella radice del modello di visualizzazione che chiama semplicemente la funzione enter sull'elemento, ma come ho detto sopra questo sembra un trucco.

risposta

6

No, questo è il modo it was designed.

Dal Documenation:

Nota 3: Utilizzo “AfterRender”, “afterAdd”, e “beforeRemove”

A volte si potrebbe desiderare di eseguire su misura logica post-elaborazione sugli elementi DOM generati dai tuoi modelli. Ad esempio, se stai utilizzando una libreria di widget JavaScript come l'interfaccia utente di jQuery, potresti voler intercettare l'output dei modelli in modo da poter eseguire comandi dell'interfaccia utente jQuery su di essa per trasformare alcuni elementi renderizzati in selettori di date, cursori o qualunque altra cosa.

In generale, il modo migliore per effettuare tale post-elaborazione su elementi DOM è quello di scrivere un custom binding, ma se si vuole veramente solo per accedere agli elementi DOM prime emessi da un modello, è possibile utilizzare AfterRender.

passare un riferimento funzione (o un valore letterale di funzione, o dare il nome di una funzione sul vostro vista del modello), e Knockout invocherà subito dopo il rendering o ri-rendering del modello.

(sottolineatura mia)


Come si dice, un legame personalizzato è un altro modo per farlo, e può essere migliore a seconda di ciò che la funzione enter() fa.

+1

copiando e incollando la documentazione e rispondendo alla domanda non sono sempre la stessa cosa. Avevo già letto i documenti. Anche se so che non è sempre il caso su questo forum, quindi ho rimosso il downvote. Quello era solo la frustrazione di parlare ... – nicholas

+0

@nicholas Ci dispiace che ti frustrato, non stavo cercando di spazzolare la tua domanda off. Ho provato a fare di più che incollare la documentazione, ma la spiegazione al di là di questo era piuttosto semplice. Sembravi chiedere perché si comportava in quel modo, e la risposta è: perché è stato progettato per. – Tyrsius

+0

Sì, di fretta ho premuto il pulsante giù prima che ci pensassi. Hai ragione, certo. Ho modificato la domanda per essere più chiara. Se quello che sto cercando di fare (avere una funzione personalizzata, specifica di un oggetto, afterAdd) non è quello che fa knockout di default, allora la domanda diventa: come faccio a fare ciò che voglio? C'è un trucco che non vedo? O un pezzo di codice che fluttua là fuori che potrei usare? Non voglio davvero sprecare una giornata ricostruire il legame se qualcuno ha già fatto il lavoro per me ... – nicholas

5

sottolineatura antirimbalzo (_.debounce) è una grande soluzione in tal caso.

modello

data-bind=" template: {foreach:myObservableArray, afterRender: runWhenAllRenderDone } 

funzione antirimbalzo verrà eseguita se AfterRender non viene generato negli ultimi 100 milisecond.

var runWhenAllRenderDone = _.debounce(myFunction, 100); 

function myFunction(){ 
    //do some task but do it for once only 
} 

non è fantastico?

+0

che dovrebbero essere antirimbalzo sottolineatura, non Backbone foreach. – LocalPCGuy

+0

+1 Nel mio caso, io non posso usare 'AfterRender' per essere sicuri che l'Engin di eliminazione diretta hanno finito il rendering html perché ho incapsulato la logica della funzione che cambiano elementi nel observableArray; il codice non è accessibile dall'html. So che non è elegante ma uso anche un timeout di x millisecondi prima di chiamare un'altra funzione che sta aggiungendo css ai nuovi elementi. In realtà, ho appena impostato un timeout di 1 millisecondi e dopo l'aggiornamento i miei pagina decine di volte, non vedo alcun caso in cui il mio html non viene aggiornata in modo corretto. Grazie. – Samuel

Problemi correlati