Esta es una gran pregunta. La columna vertebral es excelente debido a la falta de suposiciones que hace, pero significa que debe (decidir cómo) implementar cosas como esta usted mismo. Después de revisar mis propias cosas, descubro que (más o menos) uso una combinación de escenario 1 y escenario 2. No creo que exista un cuarto escenario mágico porque, simplemente, todo lo que haces en los escenarios 1 y 2 debe ser hecho.
Creo que sería más fácil explicar cómo me gusta manejarlo con un ejemplo. Digamos que tengo esta página simple dividida en las vistas especificadas:
Digamos que el HTML es, después de ser renderizado, algo como esto:
<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>
Esperemos que sea bastante obvio cómo el HTML coincide con el diagrama.
El ParentView
sostiene 2 vistas secundarias, InfoView
y PhoneListView
así como algunos divs adicionales, uno de los cuales, #name
, se debe establecer en algún momento. PhoneListView
contiene vistas secundarias propias, una serie de PhoneView
entradas.
Entonces a su pregunta real. Manejo la inicialización y el renderizado de manera diferente según el tipo de vista. Divido mis puntos de vista en dos tipos, Parent
puntos de vista y Child
puntos de vista.
La diferencia entre ellos es simple, las Parent
vistas tienen vistas secundarias mientras que las Child
vistas no. Entonces, en mi ejemplo, ParentView
y PhoneListView
son Parent
vistas, while InfoView
y las PhoneView
entradas son Child
vistas.
Como mencioné antes, la mayor diferencia entre estas dos categorías es cuando se les permite renderizar. En un mundo perfecto, quiero que las Parent
vistas solo se muestren una vez. Depende de sus vistas secundarias manejar cualquier representación cuando los modelos cambien. Child
vistas, por otro lado, permito volver a renderizar en cualquier momento que lo necesiten, ya que no tienen ninguna otra vista que se base en ellas.
En un poco más de detalle, para las Parent
vistas me gusta que mis initialize
funciones hagan algunas cosas:
- Inicializar mi propia vista
- Render mi propio punto de vista
- Cree e inicialice las vistas secundarias.
- Asigne a cada vista secundaria un elemento dentro de mi vista (por ejemplo,
InfoView
se le asignaría #info
).
El paso 1 se explica por sí mismo.
El paso 2, la representación, se realiza para que los elementos en los que se basan las vistas secundarias ya existan antes de que intente asignarlos. Al hacer esto, sé que todos los niños events
estarán configurados correctamente, y puedo volver a renderizar sus bloques tantas veces como quiera sin preocuparme de tener que volver a delegar nada. En realidad, no veo render
ningún punto de vista infantil aquí, les permito que lo hagan dentro de los suyos initialization
.
Los pasos 3 y 4 se manejan realmente al mismo tiempo que paso el
al crear la vista secundaria. Me gusta pasar un elemento aquí, ya que siento que el padre debe determinar dónde, según su propia opinión, el niño puede poner su contenido.
Para la representación, trato de mantenerlo bastante simple para las Parent
vistas. Quiero que la render
función no haga nada más que representar la vista principal. Sin delegación de eventos, sin representación de vistas secundarias, nada. Solo un simple render.
Sin embargo, a veces esto no siempre funciona. Por ejemplo, en mi ejemplo anterior, el #name
elemento deberá actualizarse cada vez que cambie el nombre dentro del modelo. Sin embargo, este bloque es parte de la ParentView
plantilla y no es manejado por una Child
vista dedicada , así que evito eso. Crearé algún tipo de subRender
función que solo reemplace el contenido del #name
elemento, y no tenga que desechar todo el #parent
elemento. Esto puede parecer un truco, pero realmente he descubierto que funciona mejor que tener que preocuparme por volver a representar todo el DOM y volver a conectar elementos y demás. Si realmente quisiera hacerlo limpio, crearía una nueva Child
vista (similar a la InfoView
) que manejaría el #name
bloque.
Ahora, para las Child
vistas, initialization
es bastante similar a las Parent
vistas, solo que sin la creación de más Child
vistas. Entonces:
- Inicializar mi vista
- La configuración se vincula a la escucha de cualquier cambio en el modelo que me interesa
- Render mi punto de vista
Child
La visualización de renderizado también es muy simple, solo renderiza y configura el contenido de mi el
. Una vez más, no te metas con la delegación ni nada de eso.
Aquí hay un código de ejemplo de cómo se ParentView
puede ver mi :
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);
}
});
Puedes ver mi implementación de subRender
aquí. Al tener cambios vinculados en subRender
lugar de render
, no tengo que preocuparme por volar y reconstruir todo el bloque.
Aquí hay un código de ejemplo para el InfoView
bloque:
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());
}
});
Los enlaces son la parte importante aquí. Al vincularme a mi modelo, nunca tengo que preocuparme de llamarme manualmente render
. Si el modelo cambia, este bloque se volverá a representar sin afectar ninguna otra vista.
El PhoneListView
será similar a la ParentView
, usted sólo necesita un poco más de la lógica, tanto en sus initialization
y render
funciones a las colecciones de la manija. La forma en que maneja la colección depende de usted, pero al menos deberá escuchar los eventos de la colección y decidir cómo desea renderizar (agregar / eliminar o simplemente volver a renderizar todo el bloque). Personalmente, me gusta agregar nuevas vistas y eliminar las viejas, no volver a renderizar toda la vista.
El PhoneView
será casi idéntico al InfoView
sólo escuchar a los cambios en el modelo que se preocupa.
Espero que esto haya ayudado un poco, avíseme si algo es confuso o no está lo suficientemente detallado.