Это большой вопрос. Магистраль великолепна из-за отсутствия допущений, которые она делает, но это означает, что вы должны (решить, как) реализовать подобные вещи самостоятельно. Просматривая свои собственные материалы, я обнаружил, что я (вроде) использую сочетание сценария 1 и сценария 2. Я не думаю, что существует четвертый магический сценарий, потому что достаточно просто все, что вы делаете в сценарии 1 и 2, должно быть сделано.
Я думаю, что было бы проще объяснить на примере, как мне нравится справляться с этим. Скажем, у меня есть эта простая страница, разбитая на указанные виды:

Скажем, HTML после рендеринга выглядит примерно так:
<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>
Надеюсь, это довольно очевидно, как HTML совпадает с диаграммой.
ParentViewИмеет 2 дочерние представления, InfoViewи PhoneListView, а также несколько дополнительных дивы, один из которых, #name, должен быть установлен в какой - то момент. PhoneListViewсодержит собственные дочерние представления, массив PhoneViewзаписей.
Итак, к вашему актуальному вопросу. Я занимаюсь инициализацией и рендерингом по-разному в зависимости от типа представления. Я делю свои взгляды на два типа: Parentвзгляды и Childвзгляды.
Разница между ними проста: Parentпредставления содержат дочерние представления, а Childпредставления - нет. Так что в моем примере, ParentViewи PhoneListViewявляются Parentмнением, в то время как InfoViewи PhoneViewзаписи являются Childвзглядами.
Как я уже упоминал ранее, самая большая разница между этими двумя категориями заключается в том, что им разрешено отображать. В идеальном мире я хочу, чтобы Parentпредставления отображались только один раз. Их дочерние представления должны обрабатывать любой повторный рендеринг при изменении модели. Childвиды, с другой стороны, я разрешаю перерисовывать в любое время, когда им нужно, поскольку у них нет других представлений, полагающихся на них.
Чуть более подробно, для Parentпредставлений мне нравится, что мои initializeфункции выполняют несколько вещей:
- Инициализировать мой собственный взгляд
- Предоставить мой собственный взгляд
- Создайте и инициализируйте любые дочерние представления.
- Назначьте каждому дочернему виду элемент в моем представлении (например
InfoView, будет назначен #info).
Шаг 1 довольно понятен.
Шаг 2, рендеринг, сделан таким образом, что любые элементы, на которые полагаются дочерние представления, уже существуют, прежде чем я попытаюсь назначить их. Делая это, я знаю, что все дочерние eventsэлементы будут правильно установлены, и я могу перерисовывать их блоки столько раз, сколько захочу, не беспокоясь о необходимости повторного делегирования. На самом деле я не вижу renderздесь никаких детских взглядов, я позволяю им делать это в рамках их собственных initialization.
Шаги 3 и 4 фактически обрабатываются в то же время, что и я, elпри создании дочернего представления. Мне нравится передавать элемент здесь, так как я считаю, что родитель должен определить, где, по его собственному мнению, ребенку разрешено размещать его содержимое.
Для рендеринга я стараюсь сделать его довольно простым для Parentпредставлений. Я хочу, чтобы renderфункция не делала ничего, кроме визуализации родительского представления. Без делегирования событий, без представления дочерних представлений, ничего. Просто простой рендер.
Иногда это не всегда работает, хотя. Например, в моем примере выше, #nameэлемент должен будет обновляться каждый раз, когда меняется имя в модели. Тем не менее, этот блок является частью ParentViewшаблона и не обрабатывается специальным Childпредставлением, поэтому я работаю над этим. Я создам какую-то subRenderфункцию, которая только заменяет содержимое #nameэлемента и не должна уничтожать весь #parentэлемент. Это может показаться хаком, но я действительно обнаружил, что это работает лучше, чем беспокоиться о повторном рендеринге всего DOM и повторного присоединения элементов и тому подобного. Если бы я действительно хотел сделать его чистым, я бы создал новое Childпредставление (похожее на InfoView), которое будет обрабатывать #nameблок.
Теперь для Childпредставлений initializationэто очень похоже на Parentпредставления, только без создания каких-либо дальнейших Childпредставлений. Так:
- Инициализировать мой взгляд
- Настройка связывает прослушивание любых изменений в модели, которая мне нужна
- Отдай мой взгляд
ChildПросмотр рендеринга также очень прост, просто отрендерите и установите содержимое моего el. Опять же, не возиться с делегацией или что-то в этом роде.
Вот пример кода того, как ParentViewможет выглядеть мой :
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);
}
});
Вы можете увидеть мою реализацию subRenderздесь. При наличии изменений , связанных с subRenderвместо того render, я не должен беспокоиться о палить и восстановление всего блока.
Вот пример кода для InfoViewблока:
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());
}
});
Связи являются важной частью здесь. Привязываясь к моей модели, мне никогда не придется беспокоиться о том, чтобы позвонить renderмне вручную . Если модель изменится, этот блок будет перерисован сам, не влияя на другие виды.
Это PhoneListViewбудет аналогично тому ParentView, что вам просто понадобится немного больше логики в ваших функциях initializationи renderфункциях для обработки коллекций. То, как вы обрабатываете коллекцию, действительно зависит от вас, но вам, по крайней мере, нужно будет слушать события коллекции и решать, как вы хотите визуализировать (добавить / удалить или просто заново визуализировать весь блок). Лично мне нравится добавлять новые виды и удалять старые, а не заново отображать весь вид.
PhoneViewБудет почти идентичен InfoView, только прислушиваясь к модели изменений , которые она заботится о.
Надеюсь, это немного помогло, пожалуйста, дайте мне знать, если что-то сбивает с толку или недостаточно подробно.