Я прочитал эти две великие статьи:
Состояние контроллеров angularjs Джонатана Кримера
и
Переосмысление контроллеров AngularJS от Тодда Мотто
В этих статьях авторы говорят о правильном способе использования контроллеров (что делает их анемичными мостами между представлением и моделью) и фабриками/службами (где бизнес-логика должна действительно жить).
Это отличная информация, и я был очень рад начать реорганизацию контроллеров в одном из моих проектов, но я быстро обнаружил, что структура, показанная в статьях, ломается, если у вас есть богатая объектная модель.
Здесь приведен пример настройки из "Rethinking Angularjs Controllers":
Здесь контроллер:
app.controller('InboxCtrl', function InboxCtrl (InboxFactory) {
var vm = this;
vm.messages = InboxFactory.messages;
vm.openMessage = function (message) {
InboxFactory.openMessage(message);
};
vm.deleteMessage = function (message) {
InboxFactory.deleteMessage(message);
};
InboxFactory
.getMessages()
.then(function () {
vm.messages = InboxFactory.messages;
});
});
и здесь factory:
app.factory('InboxFactory', function InboxFactory ($location, NotificationFactory) {
factory.messages = [];
factory.openMessage = function (message) {
$location.search('id', message.id).path('/message');
};
factory.deleteMessage = function (message) {
$http.post('/message/delete', message)
.success(function (data) {
factory.messages.splice(index, 1);
NotificationFactory.showSuccess();
})
.error(function () {
NotificationFactory.showError();
});
};
factory.getMessages = function () {
return $http.get('/messages')
.success(function (data) {
factory.messages = data;
})
.error(function () {
NotificationFactory.showError();
});
};
return factory;
});
Это замечательно, и поскольку providers
(factory) являются одноточечными, данные поддерживаются в разных представлениях и могут быть доступны без необходимости перезагрузки из API.
Это работает просто отлично , если messages
- объект верхнего уровня. Но что происходит, если это не так? Что делать, если это приложение для просмотра входящих почтовых ящиков других пользователей? Возможно, вы являетесь администратором, и вы хотите иметь возможность управлять и просматривать почтовые ящики любого пользователя. Возможно, вам нужно одновременно загружать почтовые ящики нескольких пользователей. Как это работает? Проблема заключается в том, что сообщения inbox хранятся в службе, т.е. InboxFactory.messages
.
Что делать, если иерархия выглядит так:
Organization
|
__________________|____________________
| | |
Accounting Human Resources IT
| | |
________|_______ _____|______ ______|________
| | | | | | | | |
John Mike Sue Tom Joe Brad May Judy Jill
| | | | | | | | |
Inbox Inbox Inbox Inbox Inbox Inbox Inbox Inbox Inbox
Теперь messages
находятся на нескольких уровнях в иерархии и не имеют никакого значения сами по себе. Вы не можете сохранять сообщения в factory, InboxFactory.messages
, потому что вам нужно получать сообщения для нескольких пользователей за раз.
Теперь у вас будут OrganizationFactory, DepartmentFactory, UserFactory и InboxFactory. Получение "сообщений" должно быть в контексте user
, который находится в контексте department
, который находится в контексте organization
. Как и где должны храниться данные? Как его можно получить?
Итак, как это должно быть разрешено? Как структурировать контроллеры, фабрики/службы и богатые объектные модели?
В этот момент, по моему мнению, я склоняюсь к тому, чтобы держать его в курсе и не иметь богатую объектную модель. Просто сохраните объекты в области $, введенной в контроллер, и если вы перейдете к новому представлению, перезагрузите его из API. Если вы нуждаетесь, некоторые данные сохраняются в представлениях, вы можете построить этот мост с помощью службы или factory, но это не должно быть так, как вы делаете большинство.
Как другие решили это? Существуют ли какие-либо шаблоны для этого?