Ответ 1
Этот пост довольно старый, но мы рассматривали его ранее сегодня, поэтому в случае, если кто-то еще встретит его:
Для меня я действительно вижу два отдельных вопроса:
- Где должна возникать механика сбора данных и результирующего представления представления в маршрутизаторе или в представлении?
- Если представления ожидают уже разрешенные модели или они должны реагировать на модели, которые все еще могут быть загружены?
Немного о том, как мы обрабатываем его в сочетании с некоторыми личными предпочтениями:
- Ничего, хотя я бы приблизился к маршрутизатору. Маршрутизаторы должны обрабатывать маршрутизацию, представления должны обрабатывать просмотр, а что-то еще должно обрабатывать механику и рабочий процесс логики выборки Model/Collection. Мы называем это еще чем-то контроллером, которым в основном делегирует Router.
- Как указывает Юрий, "иногда" - это реальность. Я думаю, что это, вероятно, случайное решение, но в конечном итоге должно быть контрактом между контроллером и представлением, а не между Router/View.
Мне нравятся точки выстрела Юрия, с парами предостережений (с отступом):
- Маршрутизатор только знает, куда отправить пользователя
- Внешний вид знает только то, что пользователь должен просматривать (учитывая его данные)
- Предполагая, что внешний вид специфичен для внутреннего использования и является "принадлежащим" другим видом (для очистки)
- В противном случае для универсальных контейнеров (например, рендеринга в "основное" местоположение) нам было полезно иметь компонент, который управляет представлениями для определенного "раздела" на странице - мы называем это Renderer
- Внутренние представления только знают, как показать только их маленький кусочек всего этого (и может использоваться в другом месте)
- и функция рендеринга всегда показывает правильную вещь прямо сейчас.
- В случае универсального контейнера в конечном итоге это будет зависеть от Renderer
Основная причина для Renderer заключается в том, чтобы обрабатывать вещи, связанные с этим разделом, такие как очистка существующих представлений, чтобы избежать представлений призраков, прокручивание вверху на рендеринге (наш MainContentRenderer делает это) или показ счетчика в этом случае.
Пример psuedo-code-ish того, что может выглядеть, для:
- общий целевой контент цели (если он использует конкретный случай, может быть лучше с ComponentView в соответствии с примером Yuri, в зависимости от стратегии управления жизненным циклом просмотра)
- модель, которую мы должны получить и ждать
- представление, которое принимает уже загруженную модель
Маршрутизатор:
routes: {
"profile": "showProfile"
},
showProfile: function() {
return new ProfileController().showProfile();
}
ProfileController:
showProfile: function() {
//simple case
var model = new Model();
var deferredView = model.fetch.then(function() {
return new View(model);
};
MainContentRenderer.renderDeferred(deferredView);
}
MainContentRenderer:
var currentView;
renderDeferred: function(deferredView) {
showSpinner();
deferredView.then(function(view) {
this.closeSpinner();
this.closeCurrentView();
this.render(view);
}
},
render: function(view) {
currentView = view;
$('#main-content').html(view.render().el);
}
closeCurrentView: function() {
if (currentView and currentView.close()) {
currentView.close();
}
}
Представление контроллера также имеет дополнительное преимущество проверки. Например, у нас есть сложные правила для выполнения поиска по управлению URL-адресами, выбора между представлением результатов и новым поисковым представлением и выбора между кэшированным "последним" результатом поиска и выполнением нового поиска. У нас есть тесты Jasmine для контроллеров, чтобы проверить правильность всей этой логики потока. Он также обеспечивает изолированное место для управления этими правилами.