• AngularJS Service是一个函数或对象,可以使用在Angular应用中。

    AngularJS有很多内置服务,我们也可以按照自己的需要来创建服务,这里讲一下几个常用的服务。

    $HTTP

    $http服务是所有Angular服务中最为常用的内置服务之一。

    $http服务封装了浏览器原生的XMLHttpRequest对象。它只能接受一个参数,且这个参数是一个对象,包含了用来生成HTTP请求的配置内容。它返回一个Promise对象(一个原生的ES6对象,表示即将发生的事件),具有两个方法(success和error)。

    $http({
      url:'data.json',
      method:'GET'
    }).success(function(response){
      //响应成功
    }).error(function(response){
      //处理响应失败
    });
    

    使用than方法来处理回调

    $http({
      method: 'GET',
      url: 'data.js'
    }).then(function successCallback(response) {
      //响应成功
      }, function errorCallback(response) {
      //处理响应失败
    });
    

    快捷的GET/POST请求

    $http.get('date.json', config).then(successCallback, errorCallback);
    $http.post('date.json', data, config).then(successCallback, errorCallback);
    

    $location

    Angular中使用内置的$location服务来监听、操作URL,包括如下功能:

    • 获取、监听、改变地址栏的URL
    • 与URL实现双向数据绑定(地址栏变动、前进后退或者点击页面的链接均会触发)
    • 将URL对象封装成了一套方法(protocol、host、port、path、search和hash)

    $location服务的具体行为取决于它初始化时的配置。默认设置对大多数应用都是适合的,你也可以自定义配置来增加些新特性。

    $location服务初始化好以后,你就可以使用jquery风格的读写器和它交互了,你可以获取或者改变当前URL。

    $location服务的配置

    要配置$location服务,检索$locationProvider并把参数设置成以下这样:

    html5Mode(模式): {boolean}
      strue - 参阅HTML5模式
      false - 参阅Hashbang模式
      default: false
    hashPrefix(前缀): {string}
      Hashbang URLs的前缀 (在Hashbang模式中或者低级浏览器中使用)
      default: '!'
    

    配置示例

    $locationProvider.html5Mode(true).hashPrefix('!');
    

    Hashbang和HTML5模式

    $location服务有两种用来控制地址栏URL格式的配置:Hashbang模式(默认)和HTML5模式(使用HTML5历史API)。应用会使用两种模式中相同的API。

    示例

    Hashbang模式(默认mode)

    使用这个模式的话,$location会在所有浏览器中使用Hashbang URLs。

    it('should show example', inject(
      function($locationProvider) {
      $locationProvider.html5mode = false;
      $locationProvider.hashPrefix = '!';
      },
      function($location) {
      // open http://host.com/base/index.html#!/a
      $location.absUrl() == 'http://host.com/base/index.html#!/a'
      $location.path() == '/a'
      $location.path('/foo')
      $location.absUrl() == 'http://host.com/base/index.html#!/foo'
      $location.search() == {}
      $location.search({a: 'b', c: true});
      $location.absUrl() == 'http://host.com/base/index.html#!/foo?a=b&c'
      $location.path('/new').search('x=y');
      $location.absUrl() == 'http://host.com/base/index.html#!/new?x=y'
      }
    ));
    

    支持网络爬虫

    你需要添加特别的meta标记在你的文档的头部才能支持对你的AJAX应用的索引。

    <meta name="fragment" content="!" />
    

    这能让网络爬虫请求带有_escaped_fragment_形式的参数链接,这样你就能识别爬虫并且返回一个HTML的快照了。更多信息请参考 Making AJAX Applications Crawlable

    HTML5模式

    在HTML5模式中,$location服务的读写器和浏览器的URL地址通过HTML5历史API交互,这使你能用regular URL path并且搜索各组成部分,和hashbang是等效的。 如果浏览器不支持HTML5 历史API, $location服务会自动回退成使用hashbang URLs。你就不用担心浏览器的支持性了。$location服务总是会用最好的选择。

    • 在低级浏览器中使用了regular URL -> 重定向成hashbang URL
    • 在现代浏览器中打开了一个hashbang URL -> 重写成regular URL
    it('should show example', inject(
      function($locationProvider) {
      $locationProvider.html5mode = true;
      $locationProvider.hashPrefix = '!';
      },
      function($location) {
      // in browser with HTML5 history support:
      // open http://host.com/#!/a -> rewrite to http://host.com/a
      // (replacing the http://host.com/#!/a history record)
      $location.path() == '/a'
      $location.path('/foo');
      $location.absUrl() == 'http://host.com/foo'
      $location.search() == {}
      $location.search({a: 'b', c: true});
      $location.absUrl() == 'http://host.com/foo?a=b&c'
      $location.path('/new').search('x=y');
      $location.url() == 'new?x=y'
      $location.absUrl() == 'http://host.com/new?x=y'
      // in browser without html5 history support:
      // open http://host.com/new?x=y -> redirect to http://host.com/#!/new?x=y
      // (again replacing the http://host.com/new?x=y history item)
      $location.path() == '/new'
      $location.search() == {x: 'y'}
      $location.path('/foo/bar');
      $location.path() == '/foo/bar'
      $location.url() == '/foo/bar?x=y'
      $location.absUrl() == 'http://host.com/#!/foo/bar?x=y'
      }
    ));
    

    $cacheFactory

    $cacheFactory是应用程序一个会话(Session)中的缓存服务,以key-value对的方法存储一些临时数据。它跟浏览器本地缓存localStorage是不一样的。$cacheFactory在用户删除当前会话(比如强制刷新页面)之后,缓存的数据就被清空了。

    用法

    首先,要得到一个缓存实例,用id来区分,比如我想取id为’firstCache’的缓存:

    var cache = $cacheFactory('firstCache');
    

    添加kv对,put方法:

    cache.put(key, value);
    

    获取,get方法:

    cache.get(key); // 如果不存在这个key的话,会返回undefined
    

    添加kv对,put方法:

    cache.put(key, value);
    

    删除,remove和removeAll:

    cache.remove(key); // 删除某个kv对
    cache.removeAll(); // 删除该缓存的全部kv对
    

    删除该缓存实例,destroy:

    cache.destroy(); // 把当前缓存删除掉
    cache.put(key, value); // 错误!不能再访问该缓存,要重新生产一个实例出来
    

    $timeout、$interval

    $timeout和$interval是AngularJS自带的服务,跟原生js中的setTimeout和setInterval函数的用法基本是一样的。但是有两个不一样的地方需要注意一下:

    区别一:

    原生js中的两个函数,如果在AngularJS中使用并且在回调函数中需要使用$scope服务的话,我们需要用$angular.$apply把回调函数包起来,因为这里setTimeout函数被AngularJS当作是外部函数了。就像这样:

    // 错误的写法示例(使用setTimeout却没有用$apply):
    angular.module('myDemo', [])
      .controller('firstController', ['$scope', function ($scope) {
      setTimeout(function () {
        console.log('before');  // 正常输出before
        $scope.name = "My name have been changed."; // 这一句不被执行
        console.log('after');   // 正常输出after
      }, 2000);
      }]);
    
    // 正确的写法示例
    angular.module('myDemo', [])
      .controller('firstController', ['$scope', function ($scope) {
      setTimeout(function () {
        console.log('before');  // 正常输出before
        $scope.$apply(function () {
        $scope.name = "My name have been changed.";  // 正确显示
        });
        console.log('after');   // 正常输出after
      }, 2000);
      }]);
    

    所以,在AngularJS中,最好不要用setTimeout或setInterval,而是用那两个AngularJS系统服务。

    区别二:

    取消的方式不大一样,比如timeout:

    // setTimeout
    var id = setTimeout(func, 2000); // 返回该timeout的id
    clearTimeout(id); // 使用clearTimeout
    
    // $timeout服务
    var promise = $timeout(f, 2000); // 返回一个promise对象
    $timeout.cancel(promise); // 还是要使用服务,它的cancel方法
    

    $sce

    sce指的是Strict Contextual Escaping,它是默认开启的,负责拒绝一些不安全的行为,比如加载不同源的资源等等。但是有时候,我们又需要加载一些特定的资源,我们就得使用$sce的一些方法,来为这些资源和AngularJS系统之间建立信任。

    用法

    $sce有以下常用方法:

    • $sce.trustAsHtml(…):将一段html文本视为安全
    • $sce.trustAsUrl(…)
    • $sce.trustAsResourceUrl(…)
    • $sce.trustAsJs(…)

    举个例子,假如我要显示(可以理解成渲染,相当于android SDK中的WebView)一段html文本表示的内容,我们需要遵循以下步骤:

    1.在html模板中用“ng-bind-html”属性来绑定一个model(变量);

    2.在js中注入$sce服务,并且使用方法$sce.trustAsHtml(…),把信任后的值赋给该model。

    示例

    HTML:

    <div ng-controller="LogController">
      <!--这里不能用ng-bind,因为是渲染一段html文本,而不是显示简单的数据-->
      <div ng-bind-html="results"></div>
    </div>
    

    JS:

    angular.module('myDemo', [])
      .controller('LogController', function ($scope, $http, $sce) {
      // 随便定义一段html文本
      var txt = "<h1>Hello world!</h1>";
      // 这里不能直接$scope.results = txt,否则会报错显示“不安全”
      $scope.results = $sce.trustAsHtml(txt);
      });
    

    此时浏览器就会输出Hello world!

    (完)