Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/464.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 模型数据和行为放在哪里?[tl;dr;使用服务]_Javascript_Model View Controller_Angularjs_Dci - Fatal编程技术网

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

Javascript 模型数据和行为放在哪里?[tl;dr;使用服务],javascript,model-view-controller,angularjs,dci,Javascript,Model View Controller,Angularjs,Dci,我正在与AngularJS合作完成我的最新项目。在文档和教程中,所有模型数据都放在控制器范围内。我理解,必须存在可供控制器使用的is,因此在相应的视图中 然而,我认为这个模型不应该在那里实际实施。它可能很复杂,例如具有私有属性。此外,您可能希望在另一个上下文/应用程序中重用它。将所有内容放入控制器完全打破了MVC模式 这同样适用于任何模型的行为。如果要使用行为并将其与数据模型分离,则必须引入其他对象来保存行为。这将通过引入角色和上下文来实现 DCI==DataC协同I交互作用 当然,模型数据和行

我正在与AngularJS合作完成我的最新项目。在文档和教程中,所有模型数据都放在控制器范围内。我理解,必须存在可供控制器使用的is,因此在相应的视图中

然而,我认为这个模型不应该在那里实际实施。它可能很复杂,例如具有私有属性。此外,您可能希望在另一个上下文/应用程序中重用它。将所有内容放入控制器完全打破了MVC模式

这同样适用于任何模型的行为。如果要使用行为并将其与数据模型分离,则必须引入其他对象来保存行为。这将通过引入角色和上下文来实现

DCI==DataC协同I交互作用

当然,模型数据和行为可以用普通javascript对象或任何“类”模式实现。但是AngularJS会怎么做呢?使用服务

所以归结到这个问题:

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;
    }]);
angular.module('job.models', [])
    .service('JobManager', ['$http', 'Job', function($http, Job) {
        return {
            getAll: function(limit) {
                var params = {"limit": limit, "full": 'true'};
                return $http.get('/api/jobs', {params: params})
                  .then(function(response) {
                    var data = response.data;
                    var jobs = [];
                    for (var i = 0; i < data.objects.length; i ++) {
                        jobs.push(new Job(data.objects[i]));
                    }
                    return jobs;
                });
            }
        };
    }])
    .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最佳实践实现与控制器解耦的模型?

DCI是一种范例,因此没有AngularJS的实现方法,无论语言支持DCI还是不支持DCI。如果您愿意使用源代码转换,那么JS可以很好地支持DCI,如果您不愿意,那么JS会有一些缺点。同样,DCI与依赖注入的关系与C#类没有关系,也绝对不是服务。因此,使用angulusJS进行DCI的最佳方式是使用JS方式进行DCI,这与DCI最初的表述方式非常接近。除非您进行源代码转换,否则您将无法完全完成转换,因为角色方法将是对象的一部分,即使在上下文之外,但这通常是基于方法注入的DCI的问题。如果您查看DCI的权威站点,您可以查看ruby实现,它们也使用方法注入,或者您可以查看DCI的更多信息。主要是RUby示例,但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);
   };
}

如果希望多个控制器都能使用某些服务,则应该使用服务。下面是一个简单的人为示例:

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
}

我目前正在尝试这种模式,虽然不是DCI,但它提供了一种经典的服务/模型解耦(与web服务对话的服务(又名模型CRUD)以及定义对象属性和方法的模型)

请注意,我只在模型对象需要对其自身的属性使用方法时才使用此模式,我可能会在任何地方使用这些方法(例如改进的getter/setter)。我不是提倡对每项服务都系统地这样做

编辑: 我过去认为这种模式与“角度模型是简单的老javascript对象”的口号背道而驰,但现在我觉得这种模式非常好。

编辑(2): 更清楚地说,我只使用模型类来考虑简单的getter/setter(例如:在视图模板中使用)。对于大型业务逻辑,我建议使用单独的服务,这些服务“了解”模型,但与模型保持分离,并且只包括业务逻辑。如果您愿意,可以将其称为“业务专家”服务层

service/ElementServices.js(注意声明中如何注入元素)

model/Element.js(使用angularjs工厂,用于对象创建)


Angularjs文件明确指出:

与许多其他框架不同,Angular没有任何限制或限制 对模型的要求。没有可从或继承的类 用于访问或更改模型的特殊访问器方法。这个 模型可以是基元、对象哈希或完整对象类型。简言之 该模型是一个普通的JavaScript对象

-

这意味着如何声明模型取决于您。 它是一个简单的Javascript对象


我个人不会使用Angular服务,因为它们的行为类似于单例对象,您可以使用它们来保持整个应用程序的全局状态。

这篇关于AngularJS中模型的文章可能会有所帮助:


正如其他海报所述,Angular没有提供现成的建模基类,但可以提供以下几个功能:

  • 与RESTful API交互并创建新对象的方法
  • 建立模型之间的关系
  • 在持久化到后端之前验证数据;对于显示实时错误也很有用
  • 缓存和延迟加载以避免产生浪费的HTTP请求
  • 状态机挂钩(保存、更新、创建、新建等之前/之后)
  • ngActiveResource()是一个能够很好地完成所有这些工作的库。完全公开——我编写了这个库——我已经成功地将它用于构建多个企业级应用程序。它经过了良好的测试,并提供了Rails开发人员应该熟悉的API


    我和我的团队继续积极开发这个库,我希望看到更多的Angular开发者为它做出贡献,并对它进行测试

    我已经试着解决这个问题了

    基本上,数据建模的最佳场所是服务和工厂。然而,根据您检索数据的方式和所需行为的复杂性,有很多方法
    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;
        }]);
    
    angular.module('job.models', [])
        .service('JobManager', ['$http', 'Job', function($http, Job) {
            return {
                getAll: function(limit) {
                    var params = {"limit": limit, "full": 'true'};
                    return $http.get('/api/jobs', {params: params})
                      .then(function(response) {
                        var data = response.data;
                        var jobs = [];
                        for (var i = 0; i < data.objects.length; i ++) {
                            jobs.push(new Job(data.objects[i]));
                        }
                        return jobs;
                    });
                }
            };
        }])
        .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;
        });