Angular 应用程序、服务和工厂

Angular application, services and factories

我有以下 Angular 代码:

  var application = angular.module('Application', []);

  application.controller('ImageController', function ImageController($scope, $http) {

    $http.get('api/images').
      success(function (data, status, headers, config) {
        $scope.images = data;
      }).
      error(function (data, status, headers, config) { });

    $scope.vote = function (image) {

      $http.post('api/images/{key}/vote', { key: image.Key }).
        success(function (data, status, headers, config) {
        }).
        error(function (data, status, headers, config) {
        });

    };

  });
  1. 当控制器共享同一个应用程序时,如何在不同的文件中放置控制器? 我想我应该使用不同的方式定义控制器: application.controller('ImageController', ...

  2. 我想我应该从控制器中删除 $http 部分,对吧? 我正在阅读 Angular 工厂和服务,但我不确定该使用哪个。

    我对工厂的解释是按要求提供服务。 至少这是通常在 C# 中使用的方式。

    但在我的示例中,我应该如何删除服务/工厂的 $http 部分?

    以及如何在Controller中注入?

1) 你只是在新文件中调用模块,但不要重新定义它:

var application = angular.module('Application'); // no second parameter!

application.controller('newController', ...

或者,如果 application 是全局的,则省略第一行。从技术上讲,每个文件可以有一个控制器,没问题。

注意:必须省略module()方法中的第二个参数,见Creation versus Retrieval这里:https://docs.angularjs.org/guide/module

2) 是的,那些东西通常都放在services/factories:

工厂

application.service('myService', function($http) {
    return {
        getStuff: function() { 
            return $http.get('api/images');
        },
        postStuff: function(image) { 
            return $http.post('api/images/{key}/vote', { key: image.Key });
        }
    }
});

控制器:

application.controller('ImageController', function ($scope, myService) {

   myService.getStuff()
      .success(function (data, status, headers, config) {
        $scope.images = data;
      })
      .error(function (data, status, headers, config) { });

   $scope.vote = function (image) {

     myService.postStuff(image)
        .success(function (data, status, headers, config) {
        })
        .error(function (data, status, headers, config) {
        });

    };

  });

请注意,我必须将该服务作为依赖项注入到控制器中。


在这里查看完整的工作版本(我添加了一个假的 json 文件,因为我们无法访问 API,当然)。它在单独的文件中显示代码,以及如何与服务交互:http://plnkr.co/edit/rOG0XSxf2qE70Wyw1a8N?p=preview

控制器函数接受一个函数的第二个参数,这个函数ImageController可以在任何地方定义,包括另一个文件。

需要记住一些事情,您需要使用要注入的服务数组定义 $inject 属性 以确保缩小安全。

var application = angular.module('Application', []);
application.controller('ImageController', ImageController);

然后在其他地方:

function ImageController($scope, $http) {
  $http.get('api/images').
   success(function (data, status, headers, config) {
     $scope.images = data;
  }).
  error(function (data, status, headers, config) { });

  $scope.vote = function (image) {

    $http.post('api/images/{key}/vote', { key: image.Key }).
    success(function (data, status, headers, config) {
    }).
    error(function (data, status, headers, config) {
    });

  };
}
ImageController.$inject(['$scope','$http'])

或者,您可以在控制器文件中注册您的控制器,这样您就可以只包含任何给定页面所需的控制器,但我更喜欢将我的应用程序的控制器作为一个整体捆绑在一起并缓存它。使我连接应用程序的地方存在于一个文件中,类似于其他语言生态系统中的 DI 配置

1) 如果您想将代码拆分成单独的文件,那么您可能希望在每个文件中创建一个单独的模块。然后,您可以在创建模块时通过在方括号内列出它们的名称来将这些模块添加为主应用程序模块的依赖项。请参阅下面的示例。

2) This answer很好地描述了工厂和服务之间的区别。基本上,你可以用两者做同样的事情;您只是以不同的方式编写它们。您注入 factory/service 的方式与注入其他任何东西(如 $http$scope)的方式相同。

如果你定义一个工厂,它可能看起来像这样:

MyFactory.js

(function() {
  var application = angular.module('MyFactoryModule', []);

  application.factory('MyFactory', function ($http) {
    var myFactory = {
      images: null
    };

    $http.get('api/images').
      success(function (data, status, headers, config) {
        myFactory.images = data;
      }).
      error(function (data, status, headers, config) { });

    myFactory.vote = function (image) {
     $http.post('api/images/{key}/vote', { key: image.Key }).
       success(function (data, status, headers, config) {
       }).
       error(function (data, status, headers, config) {
       });
    };

    return myFactory;
  });
})();

Application.js

(function() {
  // Notice how Application depends on MyFactoryModule
  var application = angular.module('Application', ['MyFactoryModule']);

  application.controller('ImageController', function ($scope, MyFactory) {

    // Example of how you might use MyFactory:
    MyFactory.vote(MyFactory.images[0]);

  });
})();