AngularJS模块定义了三个方法用于定义服务:factory、service、provider.
一、使用factory方法
创建服务最简单的方法就是使用module.factory方法,传入服务名称和factory函数作为参数并返回服务对象。通过工厂函数返回的对象是服务对象,工厂函数仅被调用一次,因为该对象创建和返回时使用的服务在应用程序中是必不可少的。
Note: 当心别重复使用服务名称,如果你这样做了,已存在的服务将被覆盖。
<body ng-controller="defaultCtrl"> <div class="well"> <div class="btn-group" tri-button counter="data.totalClicks" source="data.cities"> <button class="btn btn-default" ng-repeat="city in data.cities"> {{city}} </button> </div> <h5>Total Clicks: {{data.totalClicks}}</h5> </div> </body>
angular.module("exampleApp", ["customDirectives", "customServices"]) .controller("defaultCtrl", function ($scope, logService) { $scope.data = { cities: ["London", "New York", "Paris"], totalClicks: 0 }; $scope.$watch('data.totalClicks', function (newVal) { logService.log("Total click count: " + newVal); }); });
angular.module("customServices",[]) .factory("logService",function(){ var messageCount=0; return{ log:function(msg){ console.log("(LOG+"+messageCount+++")"+msg); } } })
// service中我在工厂函数里定义的messageCount变量,而不是作为服务对象的一部分。因为不想让服务的调用者能够修改该计数器,而放在服务对象的外面则意味着它无法被调用者使用。
angular.module("customDirectives",["customServices"]) .directive("triButton",function(logService){ return{ scope:{counter:"=counter"}, link:function(scope,element,attrs){ element.on("click",function(event){ logService.log("Button click:"+event.target.innerText); scope.$apply(function(){ scope.counter++; }); }) } } })
运行结果证明了服务是单例对象:
(LOG+0) Total click count:0
(LOG+1) Button click:London
(LOG+2) Total click count:1
(LOG+3) Button click:New York
二、使用service方法
使用module.service方法也可以创建服务对象,但其中稍有不同。当AngularJS需满足由factory方法定义的服务的依赖关系时,使用工厂函数返回对象很简单;但若是service方法定义服务时,AngularJS使用工厂函数返回的对象就像构造器,使用JavaScript的new关键字创建服务对象一样。
angular.module("customServices",[]) .service("logService",function(){ return{ messageCount:0, log:function(msg){ console.log(.this.messageCount++..); } } })
AngularJS将暗中使用new关键字,总体效果是让service方法作为可交换的factory方法替代品。
三、使用provider方法
module.provider方法可以让你更好控制被创建或被配置的服务对象的方式。
provider方法的参数是将被定义的服务的名称和工厂函数。工厂函数必须返回提供器对象,并在其中定义$get方法,它可以返回服务对象。
需要该服务时,AngularJS将调用factory方法获得提供器对象,然后调用$get方法获得服务对象。使用provider方法的优点是你可以为provider方法添加功能,该方法可用于配置服务对象。
AngularJS使提供器对象适用于依赖注入,使用服务的名称与Provider连接。
angular.module("exampleApp", ["customDirectives", "customServices"]) .config(function (logServiceProvider) { // 使用服务名+Provider logServiceProvider.debugEnabled(true).messageCounterEnabled(false); }) .controller("defaultCtrl", function ($scope, logService) { // 使用服务名 $scope.data = { cities: ["London", "New York", "Paris"], totalClicks: 0 }; $scope.$watch('data.totalClicks', function (newVal) { logService.log("Total click count: " + newVal); }); });
angular.module("customServices", []) .provider("logService", function () { var counter = true; var debug = true; return { messageCounterEnabled: function (setting) { if (angular.isDefined(setting)) { counter = setting; return this; } else { return counter; } }, debugEnabled: function (setting) { if (angular.isDefined(setting)) { debug = setting; return this; } else { return debug; } }, $get: function () { return { messageCount: 0, log: function (msg) { if (debug) { console.log("(LOG" + (counter ? " + " + this.messageCount++ + ") " : ") ") + msg); } } }; } } });
服务对象是单例的,一旦你对已启动的应用程序作出任何改变,所有正在使用该服务的组件都将受到影响。