Questa è un'ottima domanda La spina dorsale è eccezionale a causa della mancanza di ipotesi che fa, ma significa che devi (decidere come) implementare cose come questa da solo. Dopo aver esaminato le mie stesse cose, trovo che (tipo di) uso un mix di scenario 1 e scenario 2. Non penso che esista un quarto scenario magico perché, semplicemente, tutto ciò che fai negli scenari 1 e 2 deve essere fatto.
Penso che sarebbe più semplice spiegare come mi piace gestirlo con un esempio. Supponiamo che questa semplice pagina sia suddivisa nelle viste specificate:

Supponiamo che l'HTML sia, dopo essere stato reso, qualcosa del genere:
<div id="parent">
<div id="name">Person: Kevin Peel</div>
<div id="info">
First name: <span class="first_name">Kevin</span><br />
Last name: <span class="last_name">Peel</span><br />
</div>
<div>Phone Numbers:</div>
<div id="phone_numbers">
<div>#1: 123-456-7890</div>
<div>#2: 456-789-0123</div>
</div>
</div>
Spero che sia abbastanza ovvio come l'HTML corrisponda al diagramma.
Il ParentViewstive 2 Visto bambino, InfoViewe PhoneListViewcosì come un paio di div in più, uno dei quali, #name, deve essere impostata a un certo punto. PhoneListViewcontiene viste secondarie proprie, una matrice di PhoneViewvoci.
Quindi passiamo alla tua vera domanda. Gestisco l'inizializzazione e il rendering in modo diverso in base al tipo di vista. Suddivido le viste in due tipi, Parentviste e Childviste.
La differenza tra loro è semplice, le Parentviste mantengono le viste figlio mentre le Childviste no. Quindi nel mio esempio, ParentViewe PhoneListViewsono Parentviste, mentre InfoViewe le PhoneViewvoci sono Childviste.
Come ho detto prima, la differenza più grande tra queste due categorie è quando è consentito il rendering. In un mondo perfetto, voglio che le Parentviste vengano visualizzate solo una volta. Spetta alle loro viste figlio gestire qualsiasi nuovo rendering quando i modelli cambiano. Childle viste, d'altra parte, concedo di eseguire nuovamente il rendering in qualsiasi momento necessario poiché non hanno altre viste che fanno affidamento su di esse.
Più in dettaglio, per le Parentviste mi piace che le mie initializefunzioni facciano alcune cose:
- Inizializza il mio punto di vista
- Rendi il mio punto di vista
- Crea e inizializza le viste figlio.
- Assegna a ciascun bambino una vista a mio avviso (ad es.,
InfoViewSarebbe assegnata #info).
Il passaggio 1 è piuttosto autoesplicativo.
Il passaggio 2, il rendering, viene eseguito in modo tale che tutti gli elementi su cui si basano le viste figlio esistano già prima che provi ad assegnarli. In questo modo, so che tutti i bambini eventssaranno impostati correttamente e posso ri-renderizzare i loro blocchi tutte le volte che voglio senza preoccuparmi di dover delegare nuovamente qualsiasi cosa. In realtà non ho renderalcuna visione di bambino qui, lascio che lo facciano da soli initialization.
I passaggi 3 e 4 vengono effettivamente gestiti contemporaneamente al passaggio eldurante la creazione della vista figlio. Mi piace inserire un elemento qui perché sento che il genitore dovrebbe determinare dove a suo avviso il bambino può mettere il suo contenuto.
Per il rendering, provo a renderlo piuttosto semplice per le Parentviste. Voglio che la renderfunzione non faccia altro che rendere la vista padre. Nessuna delegazione di eventi, nessun rendering di viste figlio, niente. Solo un semplice rendering.
A volte questo non funziona sempre però. Ad esempio, nel mio esempio sopra, l' #nameelemento dovrà essere aggiornato ogni volta che cambia il nome all'interno del modello. Tuttavia, questo blocco fa parte del ParentViewmodello e non è gestito da una Childvista dedicata , quindi ci aggiro. Creerò una sorta di subRenderfunzione che sostituisce solo il contenuto #namedell'elemento e non è necessario eliminare l'intero #parentelemento. Questo può sembrare un trucco, ma ho davvero trovato che funziona meglio che doverti preoccupare di ripetere il rendering dell'intero DOM e ricollegare elementi e così via. Se volessi davvero renderlo pulito, creerei una nuova Childvista (simile alla InfoView) che gestirà il #nameblocco.
Ora per le Childviste, initializationè abbastanza simile alle Parentviste, solo senza la creazione di ulteriori Childviste. Così:
- Inizializza la mia vista
- Il programma di installazione vincola l'ascolto di eventuali modifiche al modello a cui tengo
- Rendi il mio punto di vista
Childvisualizzare il rendering è anche molto semplice, basta renderizzare e impostare il contenuto di my el. Ancora una volta, non si scherza con la delegazione o qualcosa del genere.
Ecco un esempio di codice di come ParentViewpotrebbe apparire il mio :
var ParentView = Backbone.View.extend({
el: "#parent",
initialize: function() {
// Step 1, (init) I want to know anytime the name changes
this.model.bind("change:first_name", this.subRender, this);
this.model.bind("change:last_name", this.subRender, this);
// Step 2, render my own view
this.render();
// Step 3/4, create the children and assign elements
this.infoView = new InfoView({el: "#info", model: this.model});
this.phoneListView = new PhoneListView({el: "#phone_numbers", model: this.model});
},
render: function() {
// Render my template
this.$el.html(this.template());
// Render the name
this.subRender();
},
subRender: function() {
// Set our name block and only our name block
$("#name").html("Person: " + this.model.first_name + " " + this.model.last_name);
}
});
Puoi vedere la mia implementazione di subRenderqui. Avendo le modifiche vincolate subRenderinvece di render, non devo preoccuparmi di far saltare in aria e ricostruire l'intero blocco.
Ecco un esempio di codice per il InfoViewblocco:
var InfoView = Backbone.View.extend({
initialize: function() {
// I want to re-render on changes
this.model.bind("change", this.render, this);
// Render
this.render();
},
render: function() {
// Just render my template
this.$el.html(this.template());
}
});
I vincoli sono la parte importante qui. Legando al mio modello, non devo mai preoccuparmi di chiamarmi manualmente render. Se il modello cambia, questo blocco si riattiverà da solo senza influire su altre viste.
Il PhoneListViewsarà simile a quello ParentView, avrete solo bisogno di un po 'più logica in entrambe le vostre initializatione renderle funzioni alle collezioni manico. Il modo in cui gestisci la raccolta dipende davvero da te, ma dovrai almeno ascoltare gli eventi della raccolta e decidere come renderizzare (aggiungi / rimuovi, o semplicemente esegui nuovamente il rendering dell'intero blocco). Personalmente mi piace aggiungere nuove viste e rimuovere quelle vecchie, non ricalcolare l'intera vista.
Il PhoneViewsarà quasi identico al InfoViewsolo ascoltando il modello cambia si preoccupa.
Spero che questo abbia aiutato un po ', per favore fatemi sapere se qualcosa è confuso o non abbastanza dettagliato.