模块与服务的协作

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

服务对象是单例的,一旦你对已启动的应用程序作出任何改变,所有正在使用该服务的组件都将受到影响。 

原文地址:https://www.cnblogs.com/YangqinCao/p/6017819.html