Esta é uma grande pergunta. O backbone é ótimo por causa da falta de suposições, mas significa que você precisa (decidir como) implementar coisas como essa. Depois de analisar minhas próprias coisas, acho que (meio que) uso uma mistura dos cenários 1 e 2. Não acho que exista um quarto cenário mágico porque, simplesmente, tudo o que você faz nos cenários 1 e 2 deve ser feito.
Eu acho que seria mais fácil explicar como eu gosto de lidar com isso com um exemplo. Digamos que esta página simples seja dividida nas visualizações especificadas:

Digamos que o HTML seja, depois de renderizado, algo como isto:
<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>
Espero que seja bastante óbvio como o HTML corresponde ao diagrama.
Ele ParentViewpossui 2 visualizações filho InfoViewe PhoneListViewalgumas divs extras, uma das quais #nameprecisa ser definida em algum momento. PhoneListViewpossui visualizações filho próprias, uma matriz de PhoneViewentradas.
Então, vamos à sua pergunta real. Lido com a inicialização e a renderização de maneira diferente, com base no tipo de exibição. Eu divido minhas visões em dois tipos, Parentvisões e Childvisões.
A diferença entre eles é simples: as Parentvisualizações mantêm as visualizações filho, enquanto as Childvisualizações não. Então, no meu exemplo, ParentViewe PhoneListViewsão Parentvisualizações, enquanto InfoViewe as PhoneViewentradas são Childvisualizações.
Como mencionei antes, a maior diferença entre essas duas categorias é quando elas podem ser renderizadas. Em um mundo perfeito, quero que as Parentvisualizações sejam renderizadas apenas uma vez. Cabe às exibições filhas deles lidar com qualquer nova renderização quando os modelos forem alterados. Childvisualizações, por outro lado, permito reproduzir novamente a qualquer momento, pois elas não têm outras visualizações.
Em um pouco mais detalhadamente, para Parentvisualizações, gosto de minhas initializefunções para fazer algumas coisas:
- Inicializar minha própria visão
- Renderizar minha própria visão
- Crie e inicialize todas as visualizações filho.
- Atribua a cada filho filho um elemento da minha visão (por exemplo, o
InfoViewseria atribuído #info).
O passo 1 é bastante auto-explicativo.
A etapa 2, a renderização, é feita para que todos os elementos que os filhos exibem já existam antes que eu tente atribuí-los. Ao fazer isso, eu conheço todas as criançasevents serão definidas corretamente e posso renderizar novamente seus blocos quantas vezes quiser, sem me preocupar em ter que delegar novamente nada. Na verdade, não tenho rendernenhuma visão infantil aqui, deixo que eles façam isso sozinhos initialization.
As etapas 3 e 4 são realmente tratadas ao mesmo tempo em que passo el ao criar a exibição filho. Gosto de passar um elemento aqui, pois acho que o pai deve determinar onde, em sua própria visão, o filho pode colocar seu conteúdo.
Para renderização, tento mantê-lo bastante simples para Parent visualizações. Quero que a renderfunção não faça nada além de renderizar a exibição pai. Nenhuma delegação de evento, nenhuma renderização de visualizações filho, nada. Apenas uma renderização simples.
Às vezes, isso nem sempre funciona. Por exemplo, no meu exemplo acima, o #nameelemento precisará ser atualizado sempre que o nome no modelo for alterado. No entanto, esse bloco faz parte do ParentViewmodelo e não é tratado por uma Childexibição dedicada , portanto, resolvo isso. Vou criar algum tipo de subRenderfunção que substitui apenas o conteúdo do #nameelemento e não precisa descartar o #parentelemento inteiro . Isso pode parecer um hack, mas eu realmente achei que funciona melhor do que ter que me preocupar em renderizar novamente todo o DOM e reconectar elementos. Se eu realmente quisesse torná-lo limpo, criaria uma nova Childexibição (semelhante à InfoView) que lidaria com o #namebloco.
Agora, para Childvisualizações, ela initializationé bastante semelhante às Parentvisualizações, apenas sem a criação de outras Childvisualizações. Assim:
- Inicializar minha visão
- A instalação vincula a escuta de quaisquer alterações no modelo de que me importo
- Renderizar minha visão
Childver renderização também é muito simples, basta renderizar e definir o conteúdo do meu el. Novamente, não mexa com delegação ou algo assim.
Aqui está um exemplo de código de como minha ParentViewaparência pode ser:
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);
}
});
Você pode ver minha implementação subRenderaqui. Por ter alterações vinculadas a, e subRendernão render, não preciso me preocupar em explodir e reconstruir todo o bloco.
Aqui está um código de exemplo para o InfoViewbloco:
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());
}
});
As ligações são a parte importante aqui. Ao vincular meu modelo, nunca preciso me preocupar em chamar manualmenterender me . Se o modelo for alterado, esse bloco será renderizado novamente sem afetar outras visualizações.
O PhoneListViewserá semelhante ao ParentView, você só precisa de um pouco mais lógica em ambos os seus initializatione renderfunções para coleções punho. A decisão de como você lida com a coleção é realmente sua, mas pelo menos você precisará ouvir os eventos da coleção e decidir como deseja renderizar (acrescentar / remover ou apenas renderizar novamente o bloco inteiro). Pessoalmente, gosto de acrescentar novas exibições e remover as antigas, e não renderizar novamente a exibição inteira.
O PhoneViewserá quase idêntico ao InfoView, apenas ouvindo as mudanças de modelo com as quais se preocupa.
Espero que isso tenha ajudado um pouco, por favor, deixe-me saber se algo é confuso ou não é detalhado o suficiente.