c'est une excellente question. L'épine dorsale est excellente en raison du manque d'hypothèses qu'elle fait, mais cela signifie que vous devez (décider comment) mettre en œuvre des choses comme ça vous-même. Après avoir regardé à travers mes propres trucs, je trouve que j'utilise (en quelque sorte) un mélange de scénario 1 et de scénario 2. Je ne pense pas qu'un quatrième scénario magique existe parce que, tout simplement, tout ce que vous faites dans les scénarios 1 et 2 doit être terminé.
Je pense qu'il serait plus facile d'expliquer comment j'aime le gérer avec un exemple. Supposons que cette simple page soit divisée en vues spécifiées:
Disons que le HTML est, après avoir été rendu, quelque chose comme ceci:
<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>
J'espère que la façon dont le code HTML correspond au diagramme est assez évidente.
Les ParentView
détient 2 vues de l' enfant, InfoView
et PhoneListView
ainsi que quelques divs supplémentaires, dont l' une #name
, doit être fixé à un moment donné. PhoneListView
contient ses propres vues enfants, un tableau d' PhoneView
entrées.
Passons donc à votre question réelle. Je gère l'initialisation et le rendu différemment en fonction du type de vue. Je divise mes vues en deux types, Parent
vues et Child
vues.
La différence entre les deux est simple, les Parent
vues contiennent des vues enfants, Child
contrairement aux vues. Donc, dans mon exemple, ParentView
et PhoneListView
sont des Parent
vues, tandis que InfoView
et les PhoneView
entrées sont des Child
vues.
Comme je l'ai mentionné précédemment, la plus grande différence entre ces deux catégories est le moment où elles sont autorisées à effectuer le rendu. Dans un monde parfait, je veux que les Parent
vues ne soient rendues qu'une seule fois. Il appartient à leur vue enfant de gérer tout nouveau rendu lorsque le ou les modèles changent. Child
vues, d'autre part, je permets de restituer à tout moment dont ils ont besoin car ils n'ont pas d'autres vues en s'appuyant sur eux.
Dans un peu plus de détails, pour les Parent
vues, j'aime mes initialize
fonctions pour faire quelques choses:
- Initialiser ma propre vue
- Rendre ma propre opinion
- Créez et initialisez toutes les vues enfant.
- Attribuez à chaque vue enfant un élément dans ma vue (par exemple, la
InfoView
serait attribuée #info
).
L'étape 1 est assez explicite.
L'étape 2, le rendu, est effectuée de sorte que tous les éléments sur lesquels les vues enfants s'appuient existent déjà avant que j'essaie de les affecter. Ce faisant, je sais que tous les enfants events
seront correctement définis et je peux restituer leurs blocs autant de fois que je le souhaite sans me soucier de devoir déléguer quoi que ce soit. Je n'ai pas vraiment render
d'opinion d'enfant ici, je leur permets de le faire dans le leur initialization
.
Les étapes 3 et 4 sont en fait gérées en même temps que je passe el
lors de la création de la vue enfant. J'aime passer un élément ici car je pense que le parent devrait déterminer où à son avis l'enfant est autorisé à mettre son contenu.
Pour le rendu, j'essaie de le garder assez simple pour les Parent
vues. Je veux que la render
fonction ne fasse rien de plus que rendre la vue parent. Aucune délégation d'événement, aucun rendu de vues enfants, rien. Juste un simple rendu.
Parfois, cela ne fonctionne pas toujours. Par exemple, dans mon exemple ci-dessus, l' #name
élément devra être mis à jour chaque fois que le nom dans le modèle change. Cependant, ce bloc fait partie du ParentView
modèle et n'est pas géré par une Child
vue dédiée , donc je contourne cela. Je vais créer une sorte de subRender
fonction qui ne remplace que le contenu de l' #name
élément, et je n'aurai pas à jeter la totalité de l' #parent
élément. Cela peut sembler être un hack, mais j'ai vraiment trouvé que cela fonctionnait mieux que d'avoir à se soucier de restituer l'ensemble du DOM et de rattacher les éléments et autres. Si je voulais vraiment le nettoyer, je créerais une nouvelle Child
vue (similaire à la InfoView
) qui gérerait le #name
bloc.
Maintenant, pour les Child
vues, le initialization
est assez similaire aux Parent
vues, juste sans la création d'autres Child
vues. Alors:
- Initialiser ma vue
- Le programme d'installation lie l'écoute de tout changement au modèle qui m'importe
- Rendre ma vue
Child
le rendu de vue est également très simple, il suffit de rendre et de définir le contenu de mon el
. Encore une fois, pas de problème avec la délégation ou quelque chose comme ça.
Voici un exemple de code de ce à quoi mon ParentView
peut ressembler:
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);
}
});
Vous pouvez voir ma mise en œuvre subRender
ici. En ayant des modifications liées à subRender
au lieu de render
, je n'ai pas à me soucier de dynamiter et de reconstruire le bloc entier.
Voici un exemple de code pour le InfoView
bloc:
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());
}
});
Les liens sont la partie importante ici. En me liant à mon modèle, je n'ai jamais à me soucier de render
m'appeler manuellement . Si le modèle change, ce bloc se restitue sans affecter les autres vues.
Le PhoneListView
sera similaire au ParentView
, vous aurez juste besoin d'un peu plus de logique dans vos fonctions initialization
et render
pour gérer les collections. La façon dont vous gérez la collection dépend vraiment de vous, mais vous devrez au moins écouter les événements de la collection et décider de la façon dont vous souhaitez effectuer le rendu (ajouter / supprimer ou simplement restituer le bloc entier). Personnellement, j'aime ajouter de nouvelles vues et supprimer les anciennes, pas restituer la vue entière.
Le PhoneView
sera presque identique au InfoView
, n'écoutant que les changements de modèle qui lui tiennent à cœur.
J'espère que cela a aidé un peu, s'il vous plaît laissez-moi savoir si quelque chose prête à confusion ou n'est pas assez détaillé.