zoukankan      html  css  js  c++  java
  • angularJS module里的'服务'

    首先,为了举栗子,先写好如下的模型,控制器,html:

    html:

    复制代码
    <!DOCTYPE html>
    <html ng-app="serviceApp">
    <head>
      <title>服务</title>
      <meta charset="utf-8">
      <script src="../angular.js"></script>
      <script src="script.js"></script>
    <!--  <script src="script_2.js"></script>-->
    </head>
    <body >
      <div ng-controller="myCtrl">
        name:{{name}}
        <br/>
        age:{{age}}
        <br/>
        love:{{love}}
        <br/>
        money:{{money}}
        <br/>
        id:{{id}}
      </div>
      <hr/>
      <div ng-controller="myOtherCtrl">
        name:{{name}}
        <br/>
        love:{{love}}
        <br/>
      </div>
      <hr/>
    </body>
    </html>
    复制代码

    js:

    复制代码
    var serviceApp = angular.module('serviceApp',[]);
    
    serviceApp.controller('myCtrl',function($scope,myConfig){
        $scope.name = myConfig.name;
        $scope.love = myConfig.love;
        $scope.age = myConfig.age;
        $scope.money = myConfig.money;
        $scope.id = myConfig.getId();
        $scope.$watch(myConfig.love,function(){$scope.love = myConfig.love;});
    })
    serviceApp.controller('myOtherCtrl',function($scope,myConfig){ $scope.name = myConfig.name; $scope.love = myConfig.love; angular.extend(myConfig,{love:'zxg'}); $scope.$watch(myConfig.love,function(){$scope.love = myConfig.love;}); });
    复制代码

    如上,serviceApp模型里有两个控制器,myCtrl和myOtherCtrl,这两个控制器都注入了myConfig这个服务.我们在后面就通过创建不同的myConfig服务来查看结果

    一.constant服务:

    app.constant('name',obj)

    name为服务的名字,obj为一个json对象.

    js:

    复制代码
    serviceApp.constant('myConfig',{
        name:'code_bunny',
        age:12,
        getId:function(){
            return 1
        }
    });
    复制代码

    运行结果: http://jsfiddle.net/f9qq0t50/1/

    说明:

    constant创建服务返回一个json对象(也就是第二个参数中传入的对象),这个对象里可以有参数,可以有方法,并且,属性和方法都可以在控制器中修改,新增,但是按照它的设计本意,一般constant创建的服务不会去修改它的内容,需要修改内容,最好用value来创建服务. 

    注意点:

    1.它是一个引用对象,无论被注入多少个控制器中,实际都指向同一个对象,所以,无论修改其中的哪一个,其它所有的服务都会被改变.

    2.服务修改过后,ng不会自动同步,简单的说,就是它没有做到自动双向绑定数据,比如在这里给服务新增了love属性:angular.extend(myConfig,{love:'zxg'}),我需要使用$scope.$watch(myConfig.love,function(){$scope.love = myConfig.love;})这样才能把love属性值同步到视图中.

    3.constant服务不能通过decorator进行装饰,(什么是装饰下面会讲到)

    二.value服务:

    app.value('name',obj)

    name为服务的名字,obj为一个json对象.

    js:

    复制代码
    serviceApp.value('myConfig',{
        name:'code_bunny',
        age:12,
        getId:function(){
            return 1
        }
    });
    复制代码
    serviceApp.config(function($provide){
        $provide.decorator('myConfig',function($delegate){
            $delegate.money = '100w';
            return $delegate
        })
    });

    运行结果: http://jsfiddle.net/p0dqr7wy/1/

    说明:

    value创建服务返回一个json对象(也就是第二个参数中传入的对象),这个对象里可以有参数,可以有方法,并且,属性和方法都可以在控制器中修改,新增,按照它的设计本意,如果属性和方法需要被修改内容,就用value来创建服务. 

    constant和value主要就是用于存放一些数据或方法以供使用,区别是constant一般是存放固定内容,value存放可能会被修改的内容

    注意点:

    1.同constant注意点1

    2.同constant注意点2

    3.value可以被装饰,所以这里myConfig服务拥有了money属性.(装饰具体怎么用,下面会说)

    三.factory服务

    app.factory('name',function(){return obj})

    name为服务的名字,第二个参数传入一个函数,函数需要有一个返回值obj,返回一个对象.实际被注入的服务就是这个对象.

    js:

    复制代码
    serviceApp.factory('myConfig',function(){
        var myname = 'code_bunny';
        var age = 12;
        var id = 1;
        return {
            name: myname,
            age: age,
            getId: function(){
                return id
            }
        }
    });
    复制代码

    或者是这样:

    复制代码
    serviceApp.factory('myConfig',function(){
        return new constructorFun()
    });
    
    function constructorFun(){
        var myname = 'code_bunny';
        var age = 12;
        var id = 1;
        this.name = myname;
        this.age = age;
        this.getId = function(){
            return id
        }
    }
    复制代码

    装饰部分代码:

    复制代码
    serviceApp.config(function($provide){
        $provide.decorator('myConfig',function($delegate){
            console.log($delegate);
            $delegate.money = '100w';
            return $delegate
        })
    });
    复制代码

    运行结果:

    http://jsfiddle.net/8kuxt3xc/

    http://jsfiddle.net/ua2y617q/

    说明:

    factory服务是最常见最常用的服务类型,几乎可以满足90%的自己开发的需求,使用它可以编写一些逻辑,通过这些逻辑最后返回所需要的对象.比如使用$http来获取一些数据.我们就在factory创建的服务里抓取数据,最后返回.

    它和constant,value最大的区别是,factory服务是有一个处理过程,经过这个过程,才返回结果的. 

    注意点:

    1.同constant注意点1

    2.同constant注意点2

    3.factory返回的服务也可以被装饰,所以这里myConfig服务拥有了money属性.(装饰具体怎么用,下面会说)

    四.service服务

    app.service('name',constructor)

    name为服务的名字,constructor是一个构造函数.

    js:

    复制代码
    serviceApp.service('myConfig',function(){
        var myname = 'code_bunny';
        var age = 12;
        var id = 1;
        this.name = myname;
        this.age = age;
        this.getId = function(){
            return id
        }
    });
    复制代码

    或者是这样:

    复制代码
    serviceApp.service('myConfig',constructorFun);
    function constructorFun(){
        var myname = 'code_bunny';
        var age = 12;
        var id = 1;
        this.name = myname;
        this.age = age;
        this.getId = function(){
            return id
        }
    }
    复制代码

    装饰部分代码同上.

    运行结果:

    http://jsfiddle.net/1qj8m5ot/

    http://jsfiddle.net/0bh67cog/

    说明:

    service和factory的区别在于,它第二个参数传入的是一个构造函数,最后被注入的服务是这个构造函数实例化以后的结果.所以基本上使用service创建的服务的,也都可以使用factory来创建.

    所以这里,factory服务的第二种写法和使用service是一致的:

    serviceApp.factory('myConfig',function(){
        return new constructorFun()
    });
    //等价于 serviceApp.service('myConfig',constructorFun);

    注意点:

    1.同constant注意点1

    2.同constant注意点2

    3.service返回的服务也可以被装饰,所以这里myConfig服务拥有了money属性.(装饰具体怎么用,下面会说)

    五.provider服务

    复制代码
    app.provider('name',function(){
      ....
      return {
        ...
        $get:function(){
          ...
          return obj
        }
         }
    })
    复制代码

    name为服务的名字,第二个参数接受一个函数,函数返回一个对象,返回的对象比如要有$get方法,$get方法必须要返回一个对象obj,这个对象就是真正被注入的服务.

    栗子一:

    js:

    复制代码
    serviceApp.provider('myConfig',function(){
       return {
           $get:function(){
               var myname = 'code_bunny';
               var age = 12;
               var id = 1;
               return {
                   name: myname,
                   age: age,
                   getId: function(){
                       return id
                   }
               }
           }
       }
    });
    复制代码

    装饰部分代码同上.

    运行结果: http://jsfiddle.net/2pz2ft73/

    说明:

    provider服务的第二个参数的返回值中必须要有$get方法(除了$get,还可以有其它方法,后面的例子会说到),$get方法就相当于factory服务的第二个参数,最后要返回一个对象,这个对象就是真正被注入的服务:

    栗子二:

    js:

    复制代码
    serviceApp.provider('myConfig',function(){
        var id = 1;
        return {
            setID:function(newID){
                id = newID
            },
            $get:function(){
                var myname = 'code_bunny';
                var age = 12;
                return {
                    name: myname,
                    age: age,
                    getId: function(){
                        return id
                    }
                }
            }
        }
    });
    serviceApp.config(function(myConfigProvider){
        myConfigProvider.setID(2)
    });
    复制代码

    装饰部分代码同上.

    运行结果:http://jsfiddle.net/hcpemex3/ 

    说明:

    这里的provider服务不仅仅返回了$get方法,还返回了setID方法,然后id变量是写在函数里的,返回值的外面,形成一个闭包,可以被修改.

    然后,在provider服务里定义的方法,可以在config函数里调用.注意调用的格式:

    serviceApp.config(function(myConfigProvider){
        myConfigProvider.setID(2)
    });

    被注入的服务名不叫myConfig,而是myConfigProvider.然后在函数里面可以调用myConfigProvider的setID方法(也就是myConfig的setID方法).

    通过这种方式,使得我们的服务可以被手动配置,比如这里可以配置id.

    ng有很多内置的服务都有这样的功能,比如$route服务,$location服务,当我们通过$routeProvider和$locationProvider来配置的时候,其本质就是这些服务是通过provider创建的.

    注意点:

    1.同constant注意点1

    2.同constant注意点2

    3.provider返回的服务也可以被装饰,所以这里myConfig服务拥有了money属性.(装饰具体怎么用,下面会说);

    六.装饰服务

    其实通过上面这么多的例子,看也能看懂装饰是什么了...

    app.config(function($provide){
        $provide.decorator('name',function($delegate){  
            $delegate.money = '100w';   
            return $delegate
        })
    });

    同样是通过config,在参数函数中注入$provider服务,$provider服务有个decorator方法,它接受两个参数,第一个参数'name',是要被装饰的服务的名字,第二个参数是一个函数,函数中注入$delegate,$delegate就是被装饰的服务的实例,然后在函数中操作$delegate,就相当于操作了该服务的实例.

    注意:

    1.最后一定要return $delegate,这样服务才算被装饰完成了.

    2.constant服务是不能被装饰的.

    栗子就不说了吧,上面的都是~ 

    总结上面的内容:

    1.服务的实例被注入到控制器以后,都是一个引用对象,无论被注入多少个控制器中,实际都指向同一个对象,所以,无论修改其中的哪一个,其它所有的服务都会被改变.

    2.服务的实例被修改过后,ng不会自动同步,需要使用$scope.$watch()监测其变化并手动刷新视图.

    3.constant服务不能通过decorator进行装饰.

    4.一些固定的参数和方法,使用constant

    5.可能被修改的参数和方法,使用value

    6.通过逻辑处理后得到的参数或方法,使用factory

    7.可以使用factory的也可以使用service,反之亦然(一般就是用factory)

    8.可以手动配置参数的服务,使用provider

    七.可以创建不同实例的服务

    之前我们说到,所有的服务的实例都是引用对象,无论被注入多少个控制器中,实际都指向同一个对象,所以,无论修改其中的哪一个,其它所有的服务都会被改变.这就是ng服务的设计模式,一般不需要去改变,但如果有特殊需要,要能够每次注入控制器后得到新的实例,可以这样做:

    我们给服务添加了一个方法,每次执行一次这个方法,都会创建一个新的实例,这样,虽然在控制器里注入的是服务实例还是同一个,但是在调用创建实例方法的时候,都会创建一个新的实例,然后就可以单独修改这个实例,而不会影响到其它控制器:如下

    js:

    复制代码
    var serviceApp = angular.module('serviceApp',[]);
    serviceApp.controller('myCtrl',function($scope,myConfig){
        var myConfigConstant = myConfig.create();
        $scope.name = myConfigConstant.name;
        $scope.age = myConfigConstant.age;
        angular.extend(myConfigConstant,{love:'zxg'});
        $scope.love = myConfigConstant.love;
        $scope.id = myConfigConstant.getId();
        $scope.$watch(myConfigConstant.name,function(){$scope.name = myConfigConstant.name;});
        myConfigConstant.name = 'white_bunny';
    });
    serviceApp.controller('myOtherCtrl',function($scope,myConfig){
        var myConfigConstant = myConfig.create();
        $scope.love = myConfigConstant.love;
        $scope.name = myConfigConstant.name;
        $scope.$watch(myConfigConstant.name,function(){$scope.name = myConfigConstant.name;});
    });
    
    
    /************************创建实例的服务************************/
    serviceApp.factory('myConfig',function(){
        return {
           //服务返回的对象有一个create方法,该方法每次被执行都会返回一个新的constructorFun实例 
        create: constructorFun.createNew } });
    //创建一个构造函数 function constructorFun(){ var myname = 'code_bunny'; var age = 12; var id = 1; this.name = myname; this.age = age; this.id = id }
    //给构造函数添加createNew方法,用于实例化一个constructorFun. constructorFun.createNew = function(){ return new constructorFun() };
    //给构造函数添加原型的方法.使得它的实例可以继承. constructorFun.prototype = { getId: function(){ return this.id } };
    复制代码

    运行效果: http://jsfiddle.net/fpoq4deo/1/

    好了~五种服务类型就全部讲完啦~~~ 

    全部代码托管: https://github.com/OOP-Code-Bunny/angular/tree/master/service

  • 相关阅读:
    wait/sleep/yield的区别
    54点提高PHP编程效率(转)
    ftp 使用
    转义 html 里特殊含义字符
    查看端口是否被占用
    webservice 获取调用者IP
    字符编码
    你有读过软件的协议或是网站的服务条款吗?
    使用TSQL的Rand函数生成随机数的艰苦历程
    几个.NET方面的问题——参考答案
  • 原文地址:https://www.cnblogs.com/yuanyingke/p/7682066.html
Copyright © 2011-2022 走看看