我个人喜欢保留我的代码DRY我发现,如果你在服务器 API 上保持通用约定,你可以使用基础工厂/存储库/类或任何你想调用的东西大有帮助。我在 AngularJs 中实现此目的的方法是使用返回基本存储库类的 AngularJs 工厂,即工厂返回带有原型定义的 javascript 类函数,而不是对象实例,我称之为abstractRepository
。然后,对于每个资源,我为该特定资源创建一个具体的存储库,该资源原型继承自abstractRepository
,所以我继承了所有共享/基本功能abstractRepository
并将任何资源特定功能定义到具体存储库。
我想举个例子会更清楚。假设您的服务器 API 使用以下 URL 约定(我不是最纯粹的 REST,因此我们将把约定留给您想要实现的任何内容):
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.
我个人使用矩形所以下面的例子是基于它的,但你应该能够轻松地适应它$http
or $resource
.
抽象存储库
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;
}]);
具体存储库,我们以customer为例:
app.factory('customerRepository', ['Restangular', 'abstractRepository', function (restangular, abstractRepository) {
function customerRepository() {
abstractRepository.call(this, restangular, 'customers');
}
abstractRepository.extend(customerRepository);
return new customerRepository();
}]);
然后在你的控制器中注入customerRepository
:
app.controller('CustomerController', ['$scope', 'customerRepository', function($scope, customerRepository) {
// Use your customerRepository
}]);
如果您使用此基本存储库模式,您会发现大多数 CRUD 控制器也将共享许多通用代码,因此我通常创建一个基本 CRUD 控制器,我的控制器使用它继承$injector.invoke
,但我将忽略此示例,因为它超出了这个问题的范围。