我与AngularJS工作我的最新项目。 在文档和教程的所有模型数据被置于控制器的范围。 据我所知,是具有在那里为可用于控制器,因此内相应的视图。
不过,我不认为该模型实际上应该有实现的。 这可能是复杂的,有例如私有属性。 另外一个可能想重新使用它在另一个环境/应用程序。 把什么东西都往控制器完全打破了MVC模式。
这同样适用于任何型号的行为属实。 如果我会使用DCI架构和独立的行为,从数据模型,我会介绍其他对象持有的行为。 这将通过引入角色和情境来完成。
当然,模型数据和行为可以用普通的JavaScript对象或任何“类”模式来实现。 但是,这将是AngularJS办法做到这一点? 使用服务?
所以它归结为这样一个问题:
如何实现从控制器分离机型,下面AngularJS最佳做法?
Answer 1:
如果你想通过多个控制器可用的东西,你应该使用服务。 这里有一个简单的人为的例子:
myApp.factory('ListService', function() {
var ListService = {};
var list = [];
ListService.getItem = function(index) { return list[index]; }
ListService.addItem = function(item) { list.push(item); }
ListService.removeItem = function(item) { list.splice(list.indexOf(item), 1) }
ListService.size = function() { return list.length; }
return ListService;
});
function Ctrl1($scope, ListService) {
//Can add/remove/get items from shared list
}
function Ctrl2($scope, ListService) {
//Can add/remove/get items from shared list
}
Answer 2:
目前,我想要这种模式,这虽然不是DCI,提供了一个经典的服务/模型去耦(与服务谈话Web服务(又名模型CRUD)和模型定义对象的属性和方法)。
注意每当模型对象需要方法对自己的工作性质,我只能用这种方式,我可能会到处使用(如改进的getter / setter方法)。 我不主张为每个服务系统这样做。
编辑:我曾经认为这种模式会违背“角模型是普通的老式JavaScript对象”的口号,但现在看来,我认为这个模式是完全正常的。
EDIT(2):为了更清楚,我使用模型的类只对因子简单getter / setter方法(例如:在视图模板中使用)。 对于大的业务逻辑,我建议使用单独的服务(s)表示,“知道”的模式,而是从它们处于分离状态,只有包括业务逻辑。 调用它,如果你想有一个“业务专家”服务层
服务/ ElementServices.js(注意元素是如何在声明注入)
MyApp.service('ElementServices', function($http, $q, Element)
{
this.getById = function(id)
{
return $http.get('/element/' + id).then(
function(response)
{
//this is where the Element model is used
return new Element(response.data);
},
function(response)
{
return $q.reject(response.data.error);
}
);
};
... other CRUD methods
}
模型/ Element.js(使用angularjs厂,对象创建制造)
MyApp.factory('Element', function()
{
var Element = function(data) {
//set defaults properties and functions
angular.extend(this, {
id:null,
collection1:[],
collection2:[],
status:'NEW',
//... other properties
//dummy isNew function that would work on two properties to harden code
isNew:function(){
return (this.status=='NEW' || this.id == null);
}
});
angular.extend(this, data);
};
return Element;
});
Answer 3:
该Angularjs文件明确规定:
不像许多其他框架角使得该模型没有限制或要求。 有没有类继承或访问或改变模型特殊的存取方法。 该模型可以是原始的,对象的散列,或完整的对象类型。 总之该模型是一个普通的JavaScript对象。
因此,这意味着这取决于你如何定义一个模型。 这是一个简单的JavaScript对象。
我个人不会用角服务,他们被认为表现得像你可以使用,例如,保持在你的应用程序的全局状态单一对象。
Answer 4:
DCI是一个范例,因此有做的不angularJS方式,无论是语言支持DCI或者没有。 JS支持DCI相当好,如果你愿意用源变换,并与一些缺点,如果你不是。 同样DCI有没有更多的是依赖注入不如说是一个C#类和具有绝对不是一个服务无论是。 所以,我们要做的DCI与angulusJS最好的办法是做DCI的JS的方式,这是非常接近DCI是如何在第一时间制定。 除非你做源变换,你将不能够完全做到这一点,因为角色的方法会更外的上下文对象的一部分,但通常是用注射的方法根据DCI的问题。 如果你看一下fullOO.info权威网站DCI你可以看看在Ruby实现他们也使用方法注入,或者你可以在看看这里对DCI的更多信息。 这主要是与红宝石的例子,但DCI的东西是不可知的那个。 其中一个关键DCI的是什么系统不从系统是什么分离。 因此,数据对象是非常愚蠢的,但一旦绑定到一个上下文中的角色作用的方法做出一定的行为可用。 角色是只是一个标识符,仅此而已,一个通过该标识符访问对象时则作用的方法是可用的。 有没有作用的对象/类。 随着注射的方法所描述的,但接近的作用方法作用域是不完全的。 在JS上下文的一个例子是
function transfer(source,destination){
source.transfer = function(amount){
source.withdraw(amount);
source.log("withdrew " + amount);
destination.receive(amount);
};
destination.receive = function(amount){
destination.deposit(amount);
destination.log("deposited " + amount);
};
this.transfer = function(amount){
source.transfer(amount);
};
}
Answer 5:
这篇文章车型在AngularJS可能有帮助:
http://joelhooks.com/blog/2013/04/24/modeling-data-and-state-in-your-angularjs-application/
Answer 6:
正如其他海报指出,角为造型没有超出现成的基类,但可以有效地提供几个功能:
- 对于一个RESTful API进行交互和创建新的对象方法
- 建立模型之间的关系
- 持续到后端之前验证数据; 也可用于实时显示有用的错误
- 缓存和延迟加载,以保持作出浪费HTTP请求
- 状态机钩(前/后保存,更新,创造,新等)
完成所有的这些东西一个库井ngActiveResource( https://github.com/FacultyCreative/ngActiveResource )。 充分披露 - 我写这个库 - 我已经在构建一些企业级应用程序成功地使用它。 这是很好的测试,并规定应该熟悉到Rails开发者的API。
我和我的团队继续积极发展这个图书馆,我很乐意看到更多角度的开发作出贡献和作战测试。
Answer 7:
一个旧的问题,但我认为该主题的相关性更强比以往给出的角2.0的新方向。 我会说最好的做法是写用尽可能少的依赖代码上尽可能的特定框架。 只有使用它增加了直接的价值框架特定部分。
目前,它似乎是一个角服务的几个概念,这将使它的下一代角一个,所以它可能是明智的遵循所有逻辑转移到服务的一般准则。 但是,我认为,你可以退耦模型即使没有角服务的直接依赖。 只有必要的依赖和责任创建自我包含的对象可能是要走的路。 这也使得生活在做自动化测试的时候轻松了不少。 单责任是一个时髦的工作,这些天,但它确实让很多的感觉!
这里是我考虑好了从DOM解耦的对象模型图案的例子。
http://www.syntaxsuccess.com/viewarticle/548ebac8ecdac75c8a09d58e
一个关键的目标是构造代码的方式,使得它也很容易从一个单元测试从视图中使用。 如果你做到这一点,你能很好地写现实和有用的测试。
Answer 8:
我试图解决的是准确的问题在这个博客帖子 。
基本上,数据建模最好的家是在服务和工厂。 但是,这取决于你如何获取你的数据和你所需要的行为的复杂性,有很多不同的方式去实现。 角目前还没有标准的方法或最佳实践。
岗位涵盖了三种方法,使用$ HTTP,$ 资源 , Restangular 。
这里的每个一些示例代码,使用自定义getResult()
的工作模型的方法:
Restangular(易peasy):
angular.module('job.models', [])
.service('Job', ['Restangular', function(Restangular) {
var Job = Restangular.service('jobs');
Restangular.extendModel('jobs', function(model) {
model.getResult = function() {
if (this.status == 'complete') {
if (this.passed === null) return "Finished";
else if (this.passed === true) return "Pass";
else if (this.passed === false) return "Fail";
}
else return "Running";
};
return model;
});
return Job;
}]);
$资源(稍微令人费解):
angular.module('job.models', [])
.factory('Job', ['$resource', function($resource) {
var Job = $resource('/api/jobs/:jobId', { full: 'true', jobId: '@id' }, {
query: {
method: 'GET',
isArray: false,
transformResponse: function(data, header) {
var wrapped = angular.fromJson(data);
angular.forEach(wrapped.items, function(item, idx) {
wrapped.items[idx] = new Job(item);
});
return wrapped;
}
}
});
Job.prototype.getResult = function() {
if (this.status == 'complete') {
if (this.passed === null) return "Finished";
else if (this.passed === true) return "Pass";
else if (this.passed === false) return "Fail";
}
else return "Running";
};
return Job;
}]);
$ HTTP(铁杆):
angular.module('job.models', [])
.service('JobManager', ['$q', '$http', 'Job', function($q, $http, Job) {
return {
getAll: function(limit) {
var deferred = $q.defer();
$http.get('/api/jobs?limit=' + limit + '&full=true').success(function(data) {
var jobs = [];
for (var i = 0; i < data.objects.length; i ++) {
jobs.push(new Job(data.objects[i]));
}
deferred.resolve(jobs);
});
return deferred.promise;
}
};
}])
.factory('Job', function() {
function Job(data) {
for (attr in data) {
if (data.hasOwnProperty(attr))
this[attr] = data[attr];
}
}
Job.prototype.getResult = function() {
if (this.status == 'complete') {
if (this.passed === null) return "Finished";
else if (this.passed === true) return "Pass";
else if (this.passed === false) return "Fail";
}
else return "Running";
};
return Job;
});
博客文章本身进入背后为什么你可能使用每种方法,以及如何在你的控制器使用型号代码实例推理更多详细信息:
AngularJS数据模型:$ HTTP VS $资源VS Restangular
有角2.0可能会提供一个更强大的解决方案,数据建模是得到大家在同一页上。
文章来源: Where to put model data and behaviour? [tl; dr; Use Services]