2012-04-19 28 views
8

Sto lavorando con l'applicazione di esempio Todos bundled with the latest version of Backbone (0.9.2) durante l'apprendimento di Backbone.js. La mia domanda è: perché l'app è stata progettata per attivare l'evento di rendering due volte quando si aggiunge un modello alla raccolta Todos?Backbone.js esegue il rendering rendering due volte sulla raccolta aggiungi

Se ho posto questa linea all'interno della funzione di rendering del TodoView: "Rendering"

// Re-render the titles of the todo item. 
render: function() { 
    console.log("Rendering!"); 
    this.$el.html(this.template(this.model.toJSON())); 

Poi appare due volte nella console. Capisco che questo è perché la vista si lega evento di modifica del modello di della vista di rendering:

initialize: function() { 
    this.model.bind('change', this.render, this); 

E il rendering viene chiamato in addOne, che è legato alla Todos' evento aggiuntivo:

addOne: function(todo) { 
    var view = new TodoView({model: todo}); 
    this.$("#todo-list").append(view.render().el); 
}, 

Ma è questa pratica standard di progettazione a doppio rendering? Sembra che la vista debba essere resa alla creazione (o all'entrata nel DOM), e poi di nuovo se il modello sottostante cambia. In questo caso, non viene modificato nulla, ma il rendering viene chiamato due volte.

Ancora una volta, sto imparando solo Backbone, quindi potrei avere un malinteso fondamentale che sta portando alla mia confusione.

risposta

5

Hm, ha avuto una rapida occhiata. Hai ragione che ciò accada, e no non è una pratica standard. Il motivo è un po 'oscuro, quindi portami con me;)

L'app di todo utilizza backbone-localstorage. Quando si tenta di aggiungere un nuovo elemento in app si chiama:

createOnEnter: function(e) { 
    if (e.keyCode != 13) return; 
    if (!this.input.val()) return; 

    Todos.create({title: this.input.val()}); 
    this.input.val(''); 
}, 

Avviso del Todos.create. Normalmente un create aggiunge un modello alla raccolta e lo salva sul server. L'evento add verrà quindi attivato. Accade però che backbone-localStorage fa il seguente su create:

create: function(model) { 
    if (!model.id) model.set(model.idAttribute, guid()); 
    this.data[model.id] = model; 
    this.save(); 
    return model; 
}, 

Avviso il model.set per dare al modello un id. Questo è ciò che attiva l'evento (secondo) change.

È possibile evitare che questo succeda, cambiando creare fare:

if (!model.id) model.id = guid();

+1

nice catch! .. puoi anche usare '{silent: true}' per evitare l'attivazione di eventi. – fguillen

+1

Hai ragione, questo è il motivo per cui l'evento di cambiamento è stato sparato. Tuttavia, la modifica del codice nel modo suggerito interrompe l'evento ma interrompe anche la funzionalità (non riesco più a eliminare gli elementi). Ovviamente questo non è molto importante in termini di risposta alla mia domanda, ma nel caso qualcuno in futuro legga questo, volevo farlo notare. – jcady

+0

Elimina elementi _permanently_ cioè. Dopo l'eliminazione, se aggiorno, esistono ancora. – jcady

1

Il rendering non deve essere eseguito.

Prova a debug un po 'di più. Prova di impegnare la cambiamento evento a un metodo di involucro come:

initialize: function(){ 
    this.model.bind("change", this.renderWrapper, this); 
}, 

renderWrapper: function(){ 
    console.log("in the renderWrapper"); 
    this.render(); 
} 

per essere sicuri che il secondo render() stato fatto per il cambiamento evento si legano e non per altro motivo.

+0

Hai ragione. Avrei dovuto notare nella mia domanda che inizialmente avevo ridotto il problema inserendo 'console.log ('Modifica!')' Al posto di 'this.render()'. Quindi ero sicuro che l'evento di cambiamento stava sparando. – jcady

Problemi correlati