将 CREATE 和 EDIT 控制器组合在
AngularJS?
根据我的经验,是的,在 99.9% 的情况下这是一个好主意。我通常通过 $routeProvider 解析功能将 formType 变量注入我的控制器。所以我会有以下内容:
$routeProvider
.when('/item/create', {
templateUrl: '/app/item/itemForm.html',
controller: 'itemFormController',
resolve: {
item: ['$route', 'itemRepository', function ($route, itemRepository) {
return itemRepository.getNew();
}],
formType: function () { return Enums.FormType.CREATE; }
},
})
.when('/item/edit/:itemId', {
templateUrl: '/app/item/itemForm.html',
controller: 'itemFormController',
resolve: {
item: ['$route', 'itemRepository', function ($route, itemRepository) {
return itemRepository.get($route.current.params.itemId);
}],
formType: function () { return Enums.FormType.EDIT; },
},
});
这样您就可以将实体和表单操作类型注入控制器。我也共享相同的模板,因此保存表单我可以依赖我的存储库/服务来确定要调用的 REST 端点,或者我可以根据注入的 formType 在控制器内部进行简单检查。
有没有什么好的做法可以减少重复代码?
我用来保持干燥的一些东西:
如果您在服务器 API 上保持通用约定,则可以使用基本工厂/存储库/类(无论您想调用什么)来进行数据访问。例如:
GET -> /{resource}?listQueryString // Return resource list
GET -> /{resource}/{id} // Return single resource
GET -> /{resource}/{id}/{resource}view // Return display representation of resource
PUT -> /{resource}/{id} // Update existing resource
POST -> /{resource}/ // Create new resource
etc.
然后我们使用一个 AngularJs 工厂,它返回一个基础存储库类,我们称之为abstractRepository。然后,对于每个资源,我为该特定资源创建一个具体的存储库,该资源在原型上继承自 abstractRepository,因此我从 abstractRepository 继承所有共享/基本功能,并将任何资源特定功能定义到具体存储库。这样绝大多数数据访问代码都可以在 abstractRepository 中定义。这是一个使用 Restangular 的示例:
abstractRepository
app.factory('abstractRepository', [function () {
function abstractRepository(restangular, route) {
this.restangular = restangular;
this.route = route;
}
abstractRepository.prototype = {
getList: function (params) {
return this.restangular.all(this.route).getList(params);
},
get: function (id) {
return this.restangular.one(this.route, id).get();
},
getView: function (id) {
return this.restangular.one(this.route, id).one(this.route + 'view').get();
},
update: function (updatedResource) {
return updatedResource.put();
},
create: function (newResource) {
return this.restangular.all(this.route).post(newResource);
}
// etc.
};
abstractRepository.extend = function (repository) {
repository.prototype = Object.create(abstractRepository.prototype);
repository.prototype.constructor = repository;
};
return abstractRepository;
}]);
具体的仓库,我们以客户为例:
app.factory('customerRepository', ['Restangular', 'abstractRepository', function (restangular, abstractRepository) {
function customerRepository() {
abstractRepository.call(this, restangular, 'customers');
}
abstractRepository.extend(customerRepository);
return new customerRepository();
}]);
如果您使用此基本存储库模式,您会发现大多数 CRUD 控制器也将共享许多公共代码,因此我通常创建一个基本 CRUD 控制器,我的控制器从该控制器继承。有些人不喜欢基本控制器的想法,但在我们的例子中,它也起到了作用。