zoukankan      html  css  js  c++  java
  • AngularJS入门之Services

    关于AngularJS中的DI

    在开始说AngularJS的Service之前,我们先来简单讲讲DI(Dependency Injection,通常中文称之为“依赖注入”)。

    DI是一种软件设计模式,主要为了解决组件获取它的依赖组件的问题。DI的概念渗透在AngularJS的各个地方,AngularJS使用一个专门的子系统($injector)进行DI管理,这个过程包括了创建组件、解析、获取它的依赖组件,并将这些依赖组件回传给请求组件。

    我们其实已经在不知不觉中使用DI了(比如在AngularJS自定义Directive中的出现过):

    app.directive('myCurrentTime', ['$interval', 'dateFilter', function ($interval, dateFilter) {
    }

    上述代码片段在添加Controller时,其中$interval就是Controller中依赖注入Service的推荐方法。由于$injector的存在,对于我们只需将所需服务的名称传入我们的模块即可,底层的工作都将由$injector包办。

    $injector的原理如下图:

    AngularJS中使用DI添加Service的三种方法: 

    方式1(内联注解,推荐使用):

    app.controller('myController', ['$scope', 'dateFilter', function ($scope, dateFilter) { }]);

    方式2($inject注解):

    1 var MyController = function($scope, dateFilter) {
    2   // ...
    3 }
    4 MyController.$inject = ['$scope', 'dateFilter'];
    5 someModule.controller('MyController', MyController);

    方式3(隐式注解,不推荐使用):

    app.controller('myController', function ($scope, dateFilter) { });

    推荐使用方式1的理由是:

    • 写法上比方法2更简单明了
    • 比方法3更可靠(由于Javascript可以被压缩,AngularJS又是通过解析服务名称找到对应Service的,因此Javascript压缩之后AngularJS将无法找到指定的Service,但字符串不会被压缩,因此单独以字符串指定Service的名称可以避免这个问题)

    使用方式1或方式2的注意点:

    由于上述第二点原因,AngularJS在编译Html时,由$injector将数组中Service的名称与方法体中的Service进行一一映射。这种映射关系必须遵守由AngularJS的约定:

    • 数组中Service名称的个数必须与方法体中Service名称的个数一致
    • 数组中Service的顺序必须与方法体中Serivce的顺序一致

    如果为了编码规范需要强制使用显式DI(也就是方式1或者方式2),可使用ng-strict-di属性,这样AngularJS在遇到隐式DI(也就是方式3)时将会报错。

    示例1:

     1 <!DOCTYPE >
     2 <html>
     3 <head>
     4     <script src="/Scripts/angular.js"></script>
     5     <script type="text/javascript">
     6         (function () {
     7             var app = angular.module('diTest', []);
     8 
     9             app.controller('myController1', ['$scope', function ($scope) {
    10             }]);
    11 
    12             // 方式1 隐式DI,在指定了ng-strict-di后,将会报错
    13             //app.controller('myController1', function ($scope) {
    14             //});
    15 
    16 
    17 
    18             var myController2 = function ($scope) {
    19             };
    20             myController2.$inject = ['$scope'];
    21             app.controller('myController2', myController2);
    22 
    23             // 方式2 隐式DI,在指定了ng-strict-di后,将会报错
    24             //var myController2 = function ($scope) {
    25             //};
    26             //app.controller('myController2', myController2);
    27         })();
    28     </script>
    29 </head>
    30 <body ng-app="diTest" ng-strict-di>
    31     <div ng-controller="myController1 as myCtrl1">
    32     </div>
    33 
    34     <div ng-controller="myController2 as myCtrl2">
    35     </div>
    36 </body>
    37 </html>

    示例1中,因为body使用了ng-strict-di属性,因此当使用方式1或者方式2的隐式DI时,AngularJS将会抛出如下错误:

     AngularJS中的Services:

    AngularJS提供了很多Services,常用的如$http,是集成在AngularJS和核心库中的,另外有一部分如$animate是独立的模块。由于篇幅问题,我们先以$http为例了解一下AngularJS的Service。

    迄今为止我所有的AngularJS系列的文章中,所有的数据均是通过ng-init或者在$scope中初始化数组来完成的。但实际项目中,我们的数据都会从服务器获取。写个例子来演示一下这个过程。

    Step 1,创建一个名为data.txt的文件,里面包含一个Json对象:

    {
        "students": [
            {
                "Name": "Jack", 
                "Age": 21
            }, 
            {
                "Name": "Alice", 
                "Age": 20
            }, 
            {
                "Name": "Tom", 
                "Age": 21
            }, 
            {
                "Name": "Sophie", 
                "Age": 19
            }
        ]
    }

    Step 2,使用$http的get方法获取data.txt的数据,并将数据赋值给$scope.students:

    app.controller('myController', ['$scope', '$http', function ($scope, $http) {
        $scope.students = [];
        $http.get('data.txt').
            success(function (data, status, headers, config) {
                $scope.students = data.students;
                console.log(data);
               console.log(data.students);
                 console.log($scope.students);
             }).
             error(function (data, status, headers, config) {
             });
     }]);

    Step 3,使用ng-repeat显示students的信息:

    <div ng-repeat="stu in students">
        <p>Name: {{stu.Name}}</p>
        <p>Age: {{stu.Age}}</p>
        <br />
    </div>

    完整的Html代码如下:

     1 <!DOCTYPE >
     2 <html>
     3 <head>
     4     <script src="/Scripts/angular.js"></script>
     5     <script type="text/javascript">
     6         (function () {
     7             var app = angular.module('httpServiceTest', []);
     8 
     9             app.controller('myController', ['$scope', '$http', function ($scope, $http) {
    10                 $scope.students = [];
    11                 $http.get('data.txt').
    12                   success(function (data, status, headers, config) {
    13                       $scope.students = data.students;
    14                       console.log(data);
    15                       console.log(data.students);
    16                       console.log($scope.students);
    17                   }).
    18                   error(function (data, status, headers, config) {
    19                   });
    20             }]);
    21         })();
    22     </script>
    23 </head>
    24 <body ng-app="httpServiceTest" ng-controller="myController">
    25     <div ng-repeat="stu in students">
    26         <p>Name: {{stu.Name}}</p>
    27         <p>Age: {{stu.Age}}</p>
    28         <br />
    29     </div>
    30 </body>
    31 </html>
    View Code

    关于$http:

    $http的基本调用格式:

    $http(config).success(function(data,status,headers,config){ }).error(function(data,status,headers,config){ });

    config为Json对象,完整参数说明如下:

    • method{string} - HTTP方法,示例值GET、POST等
    • url{string} - 请求资源的绝对或者相对路径,示例值 http://mytest.com/user/example 或 /myservice/user/example
    • params{Object.<string|Object>} - URL的请求参数部分,可以直接是一个完整的字符串也可以是一个对象,对象将被自动JSon序列化(一般给Get使用)
    • data{string|Object} - 请求参数内容(一般给Post使用)
    • headers{Object} - Http请求的Headers
    • xsrfHeaderName{string} - 防XSRF(跨站请求伪造)的Header名称
    • xsrfCookieName{string} - 防XSRF的Cookie名称
    • transformRequest{function(data,headersGetter)|Array.<function(data,headersGetter)>} - 自定义Http请求格式的方法
    • transformResponse{function(data, headersGetter, status)|Array.<function(data, headersGetter, status)>} - 自定义Http响应格式的方法
    • paramSerializer{string|function(Object):string} - 序列化params的方法
    • cache{boolean|Cache} - boolean类型指定是否缓存GET请求,或者指定一个由$cacheFactory创建的缓存实例
    • timeout{number|Promise} - number为请求超时时间(单位为毫秒);或者指定一个可以中断请求的promise
    • withCredentials{boolean} - 是否需要证书,详见:requests with credentials
    • responseType{string} - 返回类型,详见:requestType

     注意:由于是入门类文章,本章中对于以上各个参数的用法不深入展开了,这部分内容今后单独开一章来讨论。

    $http调用原型中,方法success和error为$http调用返回的promise,promise是由AngularJS的核心服务$q提供的一种处理异步请求的实现方式,关于promise的细节,本篇也不做展开,可参考官方文档:https://docs.angularjs.org/api/ng/service/$q。我们只需知道,由于success和error是$http方法调用返回的promise(承诺),因此在异步完成$http方法的调用完成、失败或超时后,最终必定会调用success或者error方法。

    $http的调用原型看起来比较复杂,为了便于使用,AngularJS提供了$http调用的快捷方式(如$http.get, $http.post等),其基本格式如下:

    $http.get('/someUrl').success(successCallback);
    $http.post('/someUrl', data).success(successCallback);

    $http所有方法的快捷方式(其中[config]表示config为可选参数):

    好了,通过本篇的介绍,我们已经基本了解了DI的概念,以及AngularJS中如何使用DI来完成Service的使用,我们还重点看了一下$http以及它的使用方式,当然,关于更多$http的细节今后会单独开一篇讨论的。

    如果你和我一样也是AngularJS的新手,那通过这么多天的学习后,我们已经能使用AngularJS完成一个真正的Web网站的原型的搭建了:AngularJS负责前端,数据由后端服务提供。还犹豫什么呢,赶紧自己试试吧。

    参考资料

    AngularJS官方文档DI:https://docs.angularjs.org/guide/di

    AngularJS官方文档Service:https://docs.angularjs.org/api/ng/service

  • 相关阅读:
    Android中的回调Callback
    vim编辑器配置及常用命令
    自定义View 和 ViewGroup
    BluetoothClass详解
    BluetoothServerSocket详解
    NSData转换成NSDictionary
    SDWebImage缓存图片的机制(转)
    非ARC和ARC下创建单利模式的宏定义,可以直接套用
    详细例子构建自定义cell
    使用FMDB框架来加载数据库
  • 原文地址:https://www.cnblogs.com/wushangjue/p/4533953.html
Copyright © 2011-2022 走看看