zoukankan      html  css  js  c++  java
  • AngularJS学习--- AngularJS中XHR(AJAX)和依赖注入(DI) step5

    前言:本文接前一篇文章,主要介绍什么是XHR,AJAX,DI,angularjs中如何使用XHR和DI.

    1.切换工具目录

    git checkout -f step-5 #切换分支
    npm start #启动项目

     

    2.什么是XHR和依赖注入(Dependency Injection)?

    1)什么是XHR?

    XHR是XMLHttpRequest的简称,XMLHttpRequest 用于在后台与服务器交换数据,主要是为了实现在不重新加载整个网页的情况下,对网页的某部分进行更新。简单说,浏览器中URL不变,但页面中局部元素有改变.

    XHR有两个方法open(method,url,async)和send(string);

    AJAX 指的是异步 JavaScript 和 XML(Asynchronous JavaScript and XML)。

    XMLHttpRequest 对象如果要用于 AJAX 的话,其 open() 方法的 async 参数必须设置为 true,所以可以看得出来AJAX是XHR中的一种,只不过是异步加载数据.

    2)什么是依赖注入(Dependency Injection)?

    依赖注入(Dependency Injection)即控制反转(Inversion of Control),是软件工程领域的一种设计模式,主要用来解决代码的耦合问题,也是轻量级的Spring框架的核心.

    简单说就是一段代码想共用,不想手工插入到指定位置,想注入进去,这里就可以使用DI(Dependency Injection).

    其实现方式如下:

    方式1 (基于接口): 可服务的对象需要实现一个专门的接口,该接口提供了一个对象,可以从用这个对象查找依赖(其它服务)。早期的容器Excalibur使用这种模式。
    方式2 (基于setter): 通过JavaBean的属性(setter方法)为可服务对象指定服务。HiveMind和Spring采用这种方式。
    方式3 (基于构造函数): 通过构造函数的参数为可服务对象指定服务。PicoContainer只使用这种方式。HiveMind和Spring也使用这种方式。

    依赖注入在Java后台中用到的相对较多.

    3.AngularJS中的XHR(AJAX)

    angularjs中使用$http来发出请求,接受返回过来的数据.主要支持以下几种方法:

    用法示例:

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

    其中关于jsonp的方法要注意一下,其用法如下:

    jsonp(url, [config]);官方api文档为https://docs.angularjs.org/api/ng/service/$http#jsonp .

    4.实例介绍:

    app/index.html

    <!doctype html>
    <html lang="en" ng-app="phonecatApp">
    <head>
      <meta charset="utf-8">
      <title>Google Phone Gallery</title>
      <link rel="stylesheet" href="../bower_components/bootstrap/dist/css/bootstrap.css">
      <link rel="stylesheet" href="css/app.css">
      <script src="../bower_components/angular/angular.js"></script>
      <script src="js/controllers.js"></script>
    </head>
    <body ng-controller="PhoneListCtrl">
    
      <div class="container-fluid">
        <div class="row">
          <div class="col-md-2">
            <!--Sidebar content-->
    
            Search: <input ng-model="query">
            Sort by:
            <select ng-model="orderProp">
              <option value="name">Alphabetical</option>
              <option value="age">Newest</option>
            </select>
    
          </div>
          <div class="col-md-10">
            <!--Body content-->
    
            <ul class="phones">
              <li ng-repeat="phone in phones | filter:query | orderBy:orderProp">
                <span>{{phone.name}}</span>
                <p>{{phone.snippet}}</p>
              </li>
            </ul>
    
          </div>
        </div>
      </div>
    
    </body>
    </html>
    View Code

    数据源:

    angular-phonecat/app/phones$ cat phones.json

    [
        {
            "age": 0, 
            "id": "motorola-xoom-with-wi-fi", 
            "imageUrl": "img/phones/motorola-xoom-with-wi-fi.0.jpg", 
            "name": "Motorola XOOMu2122 with Wi-Fi", 
            "snippet": "The Next, Next Generation
    
    Experience the future with Motorola XOOM with Wi-Fi, the world's first tablet powered by Android 3.0 (Honeycomb)."
        },
    
        {
        ......
        }
    ]
    
        

     数据源格式是如上面所述的json格式的数据,主要包括age,id,imageUrl,name,snippet5种属性;

    Controller(控制器)

    app/js/controllers.js:

    var phonecatApp = angular.module('phonecatApp',[]);
    
    phonecatApp.controller('PhoneListCtrl',function($scope, $http){
      $http.get('phones/phones.json').success(function(data){
        $scope.phones = data;});
    
      $scope.orderProp ='age';});

    很显示这里使用的是$http.get()方法去取的数据,跟jquery里面的get方法很类似(

    $(selector).get(url,data,success(response,status,xhr),dataType)//这里jquery中的get方法

    ),本例中url为'phones/phones.json',如果返回数据成功,那么将返回会值赋给$scope.phones,同时$scope.orderProp的默认值赋给'age',默认按age的大小来排序.

    其原理如下图所示:

    '$'前缀命名

    angularjs中对常用的方法,作用域等命名时一般会加上'$',所以自己在创建方法或service时最好不要加上'$',以免引起混淆.

    压缩js代码产生的问题

    因为AngularJS是通过控制器构造函数的参数名字来推断依赖服务名称,所有的参数也同时会被压缩,这时候依赖注入系统就不能正确的识别出服务了.

    解决方法一:

      function PhoneListCtrl($scope, $http) {...}
        PhoneListCtrl.$inject = ['$scope', '$http'];
        phonecatApp.controller('PhoneListCtrl', PhoneListCtrl);

    使用$inject方法将要做的赋值赋进去.

    解决方法二:

     function PhoneListCtrl($scope, $http) {...}
     phonecatApp.controller('PhoneListCtrl', ['$scope', '$http', PhoneListCtrl]);

    4.效果

    注:效果跟之前差不多,只不过是数据是动态加载的了,而不是写死的,而获取数据的方法就是$http.get().

    5.测试

    test/unit/controllersSpec.js 
    amosli@amosli-pc:~/develop/angular-phonecat/test/unit$ cat controllersSpec.js 
    'use strict';
    
    /* jasmine specs for controllers go here */
    describe('PhoneCat controllers', function() {
    
      describe('PhoneListCtrl', function(){
        var scope, ctrl, $httpBackend;
    
        beforeEach(module('phonecatApp'));
        beforeEach(inject(function(_$httpBackend_, $rootScope, $controller) {
          $httpBackend = _$httpBackend_;
          $httpBackend.expectGET('phones/phones.json').
              respond([{name: 'Nexus S'}, {name: 'Motorola DROID'}]);
    
          scope = $rootScope.$new();
          ctrl = $controller('PhoneListCtrl', {$scope: scope});
        }));
    
    
        it('should create "phones" model with 2 phones fetched from xhr', function() {
          expect(scope.phones).toBeUndefined();
          $httpBackend.flush();
    
          expect(scope.phones).toEqual([{name: 'Nexus S'},
                                       {name: 'Motorola DROID'}]);
        });
    
    
        it('should set the default value of orderProp model', function() {
          expect(scope.orderProp).toBe('age');
        });
      });
    });

    测试结果:

    amosli@amosli-pc:~/develop/angular-phonecat$ npm run protractor 
    ......
    Finished in 5.241 seconds
    2 tests, 5 assertions, 0 failures

    注:

    1).因为我们在测试环境中加载了Jasmineangular-mock.js,我们有了两个辅助方法,moduleinject,来帮助我们获得和配置注入器。inject方法将$rootScope$controller$httpBackend服务实例注入到Jasmine的beforeEach函数里

    2).调用$rootScope.$new()来为我们的控制器创建一个新的作用域

    3).$httpBackend.flush() 来清空(flush)请求队列

    4).expect是用来做验证的, expect(scope.orderProp).toBe('age');这个就是验证当前域下的默认排序orderProp是不是age.

  • 相关阅读:
    所谓的飞扬档案管理软件
    通过实例学习Virtools脚本语言VSL 解析字符串
    SQLite FAQ中文版
    通过实例学习Virtools脚本语言VSL 将物体排列于圆周上
    通过实例学习Virtools脚本语言VSL 解二次方程
    out 和 ref
    ASP.NET MVC深度接触:ASP.NET MVC请求生命周期
    ICSharpCode.SharpZipLib 压缩
    aspnet_regiis.exe 详解
    ASP.NET 配置文件 configSource 的用法
  • 原文地址:https://www.cnblogs.com/amosli/p/3712936.html
Copyright © 2011-2022 走看看