1. 程式人生 > >Angular內建服務

Angular內建服務

一、$http

$http是對Ajax(XHR)的封裝。這裡介紹3種用法。

1、GET請求的用法:

$http.get(url)
    .success(function (data) { 
        // 這裡的data是一個object,是我們想要的資料部分,不包含狀態碼等
        // 成功的回撥
    }).error(function (err) {
    // 出錯的回撥
});
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

2、POST請求的用法也差不多,只是多了引數:

var url = "...";
var postData = {
    id: "123",
    token: "x1234q3412fwdfw3r23"
}; $http.post(url, postData) .success(function (data) { // 成功的回撥 }).error(function (err) { // 出錯的回撥 });
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

題外話:這裡post請求的引數的資料型別,預設是“application/json”,而jQuery的post預設用的“application/x-www-form-urlencoded”。

3、jsonp:

如果不甚瞭解jsonp,可以看下這裡:http://kb.cnblogs.com/page/139725/。 
簡單來說,因為同源策略的存在,Ajax指令碼不能跨域訪問資源,所以我們只能把回撥函式作為引數之一傳給伺服器,讓伺服器端返回資料的時候指定呼叫我們的回撥函式。所以,我們只需要把回撥函式寫好就可以了,在這裡,我們寫在success中:

// 在jsonp中,url的最後必須嚴格帶上“&callback=JSON_CALLBACK”,而且名字不能改
var url = "http://www.phonegap100.com/appapi.php?a=getPortalList&catid=20&page=1&callback=JSON_CALLBACK";

$http.jsonp(url)
       .success(function (data) { // 在這裡定義JSON_CALLBACK。其實與GET差不多
            console.log('jsonp:', data)
        })
        .error(function
(err) {
console.log('error', err); });
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

此外,put、delete等,可以直接看手冊,這裡就不多說了。而且,格式都是差不多的: 
AngularJS手冊

二、$location(配合$anchorScroll)

  • 簡介:使用$location可以得到當前頁面url的引數。使用者對於Url做出的改變,會通知到$location中,而$location對Url的一些操縱也會反映到位址列上面。

  • 方法: 
    $location服務的方法

1、沒有引數時,作為getter,獲取url資訊:

在controller中注入$location服務,打印出來各個方法(程式碼就不掩飾了,直接貼結果): 
$location列印資訊

2、有引數的時候,作為setter,(部分地)改變當前url:

上面我們看到,這些方法不填入引數的話,是作為getter使用。而其中有4個方法,當填入引數的時候可以作為url的setter來使用,並且返回該$location服務(以便鏈式呼叫),這4個方法可以從上面截圖中看到: 
$location.url(urlValue) 
$location.path(pathValue) 
$location.hash(hashValue) 
$location.search(paramObj)

例子:

// 假定原來的完整url為:
// http://localhost:63342/test/templates/demo01.html#/tabs/chat?name=JK&age=10#noHash


var url = $location.url("url2").absUrl();
// 到這裡變成:
// http://localhost:63342/test/templates/demo01.html#/url2


url = $location.path("path2")
    .search({
        name: "CL",
        age: 12
    })
    .hash('hash2')
    .absUrl();
// 到這裡變成:
// http://localhost:63342/test/templates/demo01.html#/path2?name=CL&age=12#hash2
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

3、對$location.hash([id])的特別說明:

$location的hash方法填入一個DOM元素的id值,可以快速定位到該DOM元素。比如以下程式。 
程式說明:設定5個div,通過點選5個列表項可以快速定位到這5個div: 
demo01.html:

<div id="parent" ng-controller="firstController">

    <!--以下為5個列表項,可以點選,以改變hash值,定位到某個div塊-->
    <ol>
        <li ng-repeat="id in [1,2,3,4,5]" ng-click="goTo('div'+id);">Go to div{{id}}</li>
    </ol>

    <!--以下為5個div塊-->
    <div id="div1">This is div1.</div>
    <div id="div2">This is div2.</div>
    <div id="div3">This is div3.</div>
    <div id="div4">This is div4.</div>
    <div id="div5">This is div5.</div>
</div>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

css檔案就不貼出來了。以下是js檔案 
demo01_app.js:

angular.module('myDemo', [])

    .controller('firstController', ['$scope', '$location', '$anchorScroll', function ($scope, $location, $anchorScroll) {

        $scope.goTo = function (id) {
            if (id !== $location.hash()) { // 如果hash值改變了
                $location.hash(id);        // 就用hash方法,定位到那個div
            } else {             // 如果hash值沒有改變
                $anchorScroll(); // 就顯式呼叫$anchorScroll()來重新定位
            }
        }
    }]);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

效果(gif): 
hash

   這裡為什麼要用到$anchorScroll這個服務呢?通過測試我發現,如果每次都只調用hash方法來定位元素的話,會出現這麼一種情況,使得$location的hash()方法是無效的:(為了可以隨時跳轉,我把5個可點選的列表項的position屬性設成“fixed”,即固定在螢幕的某個位置)當我點選“Go to div1”的時候跳到了div1,此時Url中的hash值是“##div1”,到這裡沒問題。但這時候,如果我滾動螢幕到最底端,大概到達div5的位置的時候再點選“Go to div1”,是不能再跳轉到div1塊的,因為hash值沒有改變,$location.hash()這個方法是“無效”的。所以,這種情況就要請$anchorScroll服務出來了,它負責這種特殊情況下的跳轉,而它在這裡也只簡單地呼叫了一下方法而已。

三、$cacheFactory

1、介紹:

$cacheFactory是應用程式一個會話(Session)中的快取服務,以key-value對的方法儲存一些臨時資料。它跟瀏覽器本地快取localStorage是不一樣的。$cacheFactory在使用者刪除當前會話(比如強制重新整理頁面)之後,快取的資料就被清空了。

2、用法:

(1)首先,要得到一個快取例項,用id來區分,比如我想取id為’firstCache’的快取:

var cache = $cacheFactory('firstCache');
  • 1

(2)新增kv對,put方法:

cache.put(key, value);
  • 1

(3)獲取,get方法:

cache.get(key); // 如果不存在這個key的話,會返回undefined
  • 1

(4)新增kv對,put方法:

cache.put(key, value);
  • 1

(5)刪除,remove和removeAll:

cache.remove(key); // 刪除某個kv對
cache.removeAll(); // 刪除該快取的全部kv對
  • 1
  • 2

(6)刪除該快取例項,destroy:

cache.destroy(); // 把當前快取刪除掉

cache.put(key, value); // 錯誤!不能再訪問該快取,要重新生產一個例項出來
  • 1
  • 2
  • 3

四、$timeout、$interval

1、介紹:

$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);
    }]);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
// 正確的寫法示例
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);
    }]);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

所以,在AngularJS中,最好不要用setTimeout或setInterval,而是用那兩個AngularJS系統服務。

  • 區別二:取消的方式不大一樣,比如timeout:
// setTimeout
var id = setTimeout(func, 2000); // 返回該timeout的id
clearTimeout(id);                // 使用clearTimeout
  • 1
  • 2
  • 3
// $timeout服務
var promise = $timeout(f, 2000); // 返回一個promise物件
$timeout.cancel(promise);        // 還是要使用服務,它的cancel方法
  • 1
  • 2
  • 3

2、用法:(上面有啦~)

五、$document

1、介紹、用法:

$document是對瀏覽器物件window.document的jqLite封裝,主要操作DOM(雖然一般來說不建議在AngularJS中操作DOM)。其實,$document就等同於AngularJS中提供的另一種服務element,它也是用來把原生的DOM元素封裝成jqLite物件,即有:

$document 等效於 angular.element(document),不過要注意兩者的引用並不相等

並且,取0下標可以得到原生的document物件:

$document[0] === document,即引用相等,因為是對瀏覽器的document物件的封裝

六、$log

$log服務很簡單,就是更高階的console.log罷了,它提供5個方法:

  • log
  • warn
  • info
  • error
  • debug

是不是跟Android原生中的Log差不多呢^_^? 
官方例項: 
html:

<div ng-controller="LogController">
    <p>Reload this page with open console, enter text and hit the log button...</p>
    <label>Message:
        <input type="text" ng-model="message"/>
    </label>
    <button ng-click="$log.log(message)">log</button>
    <button ng-click="$log.warn(message)">warn</button>
    <button ng-click="$log.info(message)">info</button>
    <button ng-click="$log.error(message)">error</button>
    <button ng-click="$log.debug(message)">debug</button>
</div>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

js:

angular.module('myDemo', [])
    .controller('LogController', function ($scope, $log) {
        $scope.$log = $log;
    });
  • 1
  • 2
  • 3
  • 4

效果(瀏覽器F12開啟控制檯): 
這裡寫圖片描述

七、$sce

1、介紹

“sce”指的是“Strict Contextual Escaping”,它是預設開啟的,負責拒絕一些不安全的行為,比如載入不同源的資源等等。但是有時候,我們又需要載入一些特定的資源,我們就得使用$sce的一些方法,來為這些資源和AngularJS系統之間建立信任。

2、用法

$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>
  • 1
  • 2
  • 3
  • 4
  • 5

controller.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);
    });
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

效果: 
sce效果圖