模型数据和行为放在哪里? [tl; 博士 使用服务]

本文翻译自:Where to put model data and behaviour? [tl; dr; Use Services]

I am working with AngularJS for my latest project. 我正在为最新项目使用AngularJS。 In the documentation and tutorials all model data is put into the controller scope. 在文档和教程中,所有模型数据都放入控制器范围。 I understand that is has to be there to be available for the controller and thus within the corresponding views. 我知道控制器必须可用,因此必须在相应的视图内可用。

However I dont think the model should actually be implemented there. 但是我不认为该模型应该在那里实际实施。 It might be complex and have private attributes for example. 它可能很复杂,并且具有私有属性。 Furthermore one might want to reuse it in another context/app. 此外,可能要在另一个上下文/应用程序中重用它。 Putting everything into the controller totally breaks MVC pattern. 将所有内容放入控制器中完全破坏了MVC模式。

The same holds true for the behaviour of any model. 任何模型的行为都一样。 If I would use DCI architecture and separate behaviour from the data model, I would have to introduce additional objects to hold the behaviour. 如果我要使用DCI体系结构并将行为与数据模型分开,则必须引入其他对象来保存行为。 This would be done by introducing roles and contexts. 这可以通过介绍角色和上下文来完成。

DCI == D ata C ollaboration I nteraction DCI == d ATAÇollaboration nteraction

Of course model data and behaviour could be implemented with plain javascript objects or any "class" pattern. 当然,可以使用简单的javascript对象或任何“类”模式来实现模型数据和行为。 But what would be the AngularJS way to do it? 但是,AngularJS的实现方式是什么? Using services? 使用服务?

So it comes down to this question: 所以归结为这个问题:

How do you implement models decoupled from the controller, following AngularJS best practices? 遵循AngularJS最佳实践,如何实现与控制器分离的模型?


#1楼

参考:https://stackoom.com/question/KCTC/模型数据和行为放在哪里-tl-博士-使用服务


#2楼

DCI is a paradigm and as such there's no angularJS way of doing it, either the language support DCI or it doesn't. DCI是一个范式,因此,没有语言AngularJS的方式可以实现,无论语言是否支持DCI。 JS support DCI rather well if you are willing to use source transformation and with some drawbacks if you are not. 如果您愿意使用源代码转换,那么JS会很好地支持DCI,如果您不愿意,它会存在一些缺点。 Again DCI has no more to do with dependency injection than say a C# class has and is definitely not a service either. 再说一次,DCI与依赖注入无关,与说C#类无关,而且绝对不是服务。 So the best way to do DCI with angulusJS is to do DCI the JS way, which is pretty close to how DCI is formulated in the first place. 因此,使用angulusJS进行DCI的最佳方法是采用JS方式进行DCI,这与DCI的最初编写方式非常接近。 Unless you do source transformation, you will not be able to do it fully since the role methods will be part of the object even outside the context but that's generally the problem with method injection based DCI. 除非您进行源转换,否则您将无法完全完成转换,因为角色方法即使在上下文之外也将成为对象的一部分,但这通常是基于方法注入的DCI的问题。 If you look at fullOO.info the authoritative site for DCI you could have a look at the ruby implementations they also use method injection or you could have a look at here for more information on DCI. 如果您查看DCI的权威站点fullOO.info,则可以查看它们也使用方法注入的ruby实现,或者您可以在此处查看有关DCI的更多信息。 It's mostly with RUby examples but the DCI stuff is agnostic to that. 它主要与RUby示例有关,但DCI内容与此无关。 One of the keys to DCI is that what the system does is separated from what the system is. DCI的关键之一是系统的工作与系统的工作是分开的。 So the data object are pretty dumb but once bound to a role in a context role methods make certain behaviour available. 因此,数据对象相当笨拙,但是一旦绑定到上下文角色中,角色方法就可以使某些行为可用。 A role is simply an identifier, nothing more, an when accessing an object through that identifier then role methods are available. 角色只是一个标识符,仅此而已;当通过该标识符访问对象时,可以使用角色方法。 There's no role object/class. 没有角色对象/类。 With method injection the scoping of role methods is not exactly as described but close. 使用方法注入时,角色方法的作用域与所描述的不完全相同,而是很接近。 An example of a context in JS could be 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);
   };
}

#3楼

You should use services if you want something usable by multiple controllers. 如果您希望某些东西可以被多个控制器使用,则应该使用服务。 Here's a simple contrived example: 这是一个简单的示例:

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
}

#4楼

I'm currently trying this pattern, which, although not DCI, provides a classical service / model decoupling (with services for talking to web services (aka model CRUD), and model defining the object properties and methods). 我目前正在尝试这种模式,尽管不是DCI,但它提供了经典的服务/模型解耦(以及用于与Web服务对话的服务(又称为模型CRUD),以及定义对象属性和方法的模型)。

Note that i only use this pattern whenever the model object needs methods working on its own properties, that i'll probably use everywhere (such as improved getter/setters). 请注意,只有在模型对象需要在其自己的属性上运行方法的情况下,我才使用该模式,我可能会在任何地方使用它(例如改进的getter / setter方法)。 I'm not advocating doing this for every service systematically. 并不是在为每种服务系统地提倡这样做。

EDIT: I used to think this pattern would go against the "Angular model is plain old javascript object" mantra, but it seems to me now that this pattern is perfectly fine. 编辑:我曾经认为这种模式会违背“ Angular模型是普通的旧javascript对象”的口头禅,但是在我看来,现在这种模式非常好。

EDIT (2): To be even clearer, I use a Model class only to factor simple getters / setters (eg : to be used in view templates). 编辑(2):更清楚地说,我仅使用Model类来分解简单的getter / setter方法(例如:在视图模板中使用)。 For big business logic, i recommend using separate service(s) that "know" about the model, but are kept separated from them, and only include business logic. 对于大型业务逻辑,我建议使用“了解”模型但与它们分开的单独服务,并且仅包含业务逻辑。 Call it a "business expert" service layer if you want 如果需要,可将其称为“业务专家”服务层

service/ElementServices.js (notice how Element is injected in the declaration) service / 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
}

model/Element.js (using angularjs Factory, made for object creation) model / Element.js (使用angularjs Factory,用于创建对象)

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;
});

#5楼

The Angularjs documentation clearly states: Angularjs文档明确指出:

Unlike many other frameworks Angular makes no restrictions or requirements on the model. 与许多其他框架不同,Angular对模型没有任何限制或要求。 There are no classes to inherit from or special accessor methods for accessing or changing the model. 没有类可以继承或使用特殊的访问器方法来访问或更改模型。 The model can be primitive, object hash, or a full object Type. 该模型可以是原始的,对象哈希或完整的对象类型。 In short the model is a plain JavaScript object. 简而言之,模型是一个普通的JavaScript对象。

AngularJS Developer Guide - V1.5 Concepts - Model AngularJS开发人员指南-V1.5概念-模型

So it means that's up to you how to declare a model. 因此,这取决于您如何声明模型。 It's a simple Javascript object. 这是一个简单的Javascript对象。

I personally won't use Angular Services as they were meant to behave like singleton objects you can use, for example, to keep global states across your application. 我个人不会使用Angular Services,因为它们的作用类似于您可以使用的单例对象,例如,在应用程序中保持全局状态。


#6楼

This article about models in AngularJS might help: 关于AngularJS中的模型的本文可能会有所帮助:

http://joelhooks.com/blog/2013/04/24/modeling-data-and-state-in-your-angularjs-application/ http://joelhooks.com/blog/2013/04/24/modeling-data-and-state-in-your-angularjs-application/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值