To świetne pytanie. Szkielet jest świetny ze względu na brak założeń, które sprawia, ale oznacza to, że musisz (zdecydować, jak) wdrożyć takie rzeczy samodzielnie. Po przejrzeniu moich własnych rzeczy stwierdzam, że (w pewnym sensie) używam kombinacji scenariusza 1 i scenariusza 2. Nie sądzę, aby istniał czwarty magiczny scenariusz, ponieważ po prostu wszystko, co robisz w scenariuszu 1 i 2, musi być Gotowe.
Myślę, że najłatwiej byłoby wyjaśnić na przykład, jak lubię sobie z tym poradzić. Powiedzmy, że mam tę prostą stronę podzieloną na określone widoki:

Powiedzmy, że HTML po renderowaniu wygląda mniej więcej tak:
<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>
Mamy nadzieję, że to dość oczywiste, jak HTML pasuje do diagramu.
ParentViewPosiada 2 widoki dziecko, InfoViewi PhoneListViewjak również kilka dodatkowych div, z których jeden, #name, musi być ustawiony w pewnym momencie. PhoneListViewposiada własne widoki potomne, tablicę PhoneViewwpisów.
Tak więc na twoje aktualne pytanie. Inicjowanie i renderowanie wykonuję inaczej w zależności od typu widoku. Podzielam swoje poglądy na dwa typy: Parentwidoki i Childwidoki.
Różnica między nimi jest prosta, Parentwidoki zawierają widoki potomne, a Childwidoki nie. Więc w moim przykładzie, ParentViewi PhoneListViewsą Parentwidoki, podczas gdy InfoViewa PhoneViewwpisy są Childwidoki.
Jak wspomniałem wcześniej, największą różnicą między tymi dwiema kategoriami jest to, kiedy można je renderować. W idealnym świecie chcę, aby Parentwidoki były renderowane tylko raz. Od ich widoków podrzędnych zależy, czy każde renderowanie zostanie zmienione po zmianie modelu (ów).ChildZ drugiej strony, zezwalam na ponowne renderowanie w dowolnym momencie, ponieważ nie mają na nich żadnych innych widoków.
Bardziej szczegółowo, dla Parentwidoków lubię moje initializefunkcje, aby zrobić kilka rzeczy:
- Zainicjuj mój własny widok
- Renderuj mój własny widok
- Utwórz i zainicjuj wszelkie widoki potomne.
- Przypisz każdemu widokowi podrzędnemu element w moim widoku (np.
InfoViewZostanie przypisany #info).
Krok 1 jest dość oczywisty.
Krok 2, renderowanie, jest wykonywany, aby wszystkie elementy, na których polegają widoki potomne, już istniały, zanim spróbuję je przypisać. W ten sposób wiem, że wszystkie dzieci eventszostaną poprawnie ustawione i mogę ponownie renderować ich bloki tyle razy, ile chcę, nie martwiąc się o konieczność ponownej delegacji. W rzeczywistości nie widzę rendertutaj żadnych poglądów dzieci, pozwalam im to robić we własnym zakresie initialization.
Kroki 3 i 4 są w rzeczywistości obsługiwane w tym samym czasie, w którym przechodzę elpodczas tworzenia widoku potomnego. Lubię przekazywać tutaj element, ponieważ uważam, że rodzic powinien określić, gdzie jego zdaniem dziecko może umieścić swoją treść.
Do renderowania staram się, aby Parentwidoki były dość proste . Chcęrender funkcja nic więcej nie renderowała, niż renderowanie widoku nadrzędnego. Bez delegowania zdarzeń, bez renderowania widoków dzieci, nic. Po prostu prosty render.
Czasami jednak nie zawsze to działa. Na przykład w moim przykładzie powyżej #nameelement będzie wymagał aktualizacji za każdym razem, gdy zmieni się nazwa w modelu. Jednak ten blok jest częścią ParentViewszablonu i nie jest obsługiwany przez dedykowany Childwidok, więc omijam to. Stworzę coś w rodzaju subRenderfunkcji, która zastępuje tylko zawartość #nameelementu i nie musi niszczyć całego #parentelementu. To może wydawać się włamaniem, ale naprawdę przekonałem się, że działa lepiej niż martwić się o ponowne renderowanie całego DOM i ponowne podłączanie elementów i tym podobne. Gdybym naprawdę chciał to wyczyścić, stworzyłbym nowy Childwidok (podobny do InfoView), który obsługiwałby #nameblok.
Teraz dla Childwidoków initializationjest bardzo podobny do Parentwidoków, tylko bez tworzenia kolejnych Childwidoków. Więc:
- Zainicjuj mój widok
- Instalator wiąże nasłuchując wszelkich zmian w modelu, na którym mi zależy
- Renderuj mój widok
Childrenderowanie widoku jest również bardzo proste, wystarczy wyrenderować i ustawić zawartość mojego el. Znowu, nie zadzieraj z delegacją ani nic podobnego.
Oto przykładowy kod tego, jak ParentViewmoże wyglądać mój :
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);
}
});
Tutaj możesz zobaczyć moją implementację subRender. Mając do czynienia ze zmianami subRenderzamiast render, nie muszę się martwić o odpalenie i odbudowanie całego bloku.
Oto przykładowy kod dla InfoViewbloku:
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());
}
});
Wiązania są tutaj ważną częścią. Wiążąc się z moim modelem, nigdy nie muszę się martwić o ręczne wywołanie rendersiebie. Jeśli model się zmieni, ten blok zrenderuje się sam, bez wpływu na inne widoki.
PhoneListViewBędzie podobny do ParentView, to po prostu trzeba trochę więcej logiki w obu swoich initializationand renderfunkcje kolekcji klamek. Sposób obsługi kolekcji zależy od Ciebie, ale musisz przynajmniej wysłuchać wydarzeń związanych z kolekcją i zdecydować, jak chcesz renderować (dołączyć / usunąć lub po prostu zrenderować cały blok). Osobiście lubię dodawać nowe widoki i usuwać stare, a nie renderować cały widok.
PhoneViewBędzie prawie identyczny jak InfoViewtylko słuchać modelowych zmian to obchodzi.
Mam nadzieję, że to trochę pomogło, daj mi znać, jeśli coś jest mylące lub niewystarczająco szczegółowe.