我读了这两篇很棒的文章:
《AngularJS控制器的状态》,作者是Jonathan Creamer。
和
《重新思考AngularJS控制器》,作者是Todd Motto。
在这些文章中,作者们谈到了正确使用控制器(将它们作为连接视图和模型的贫血桥梁)和工厂/服务(业务逻辑应该真正存在的地方)的方法。
这是很好的信息,我很兴奋地开始重构我的一个项目上的控制器,但我很快发现,如果你有一个丰富的对象模型,那么这些文章中展示的结构会出现问题。
以下是从“重新思考AngularJS控制器”中的设置摘要:
这是控制器:
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;
});
});
这是工厂:
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
(工厂)是单例模式,因此数据在视图之间保持,并且可以访问而无需从API重新加载。
如果messages
不是顶级对象会怎么样呢?如果这是一个用于浏览其他用户收件箱的应用程序呢?也许您是管理员,希望能够管理和浏览任何用户的收件箱。也许您需要同时加载多个用户的收件箱。这该怎么办?问题在于收件箱消息存储在服务中,即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
在层次结构中有几个级别,本身没有意义。您无法将消息存储在工厂中,InboxFactory.messages
,因为您必须一次为多个用户检索消息。
现在,您将拥有一个OrganizationFactory、DepartmentFactory、UserFactory和InboxFactory。检索“messages”必须处于user
的上下文中,而该上下文又处于department
的上下文中,department
又处于organization
的上下文中。数据应该存储在何处?如何检索它?
那么这应该如何解决?控制器、工厂/服务和丰富的对象模型应该如何构建?
在我的思考中,我倾向于保持简洁,不使用丰富的对象模型。只需将对象存储在注入到控制器中的$scope上,如果要导航到新视图,则从API重新加载。如果您需要跨视图保留某些数据,可以使用服务或工厂构建该桥梁,但这不应该是您完成大部分事情的方式。
其他人如何解决这个问题?是否有什么模式可用?
GET /messages
仅返回John的消息,并且界面与组织老板在登录时看到的界面不同。 - terafor