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等,可以直接看手冊,這裡就不多說了。而且,格式都是差不多的:
二、$location(配合$anchorScroll)
-
簡介:使用$location可以得到當前頁面url的引數。使用者對於Url做出的改變,會通知到$location中,而$location對Url的一些操縱也會反映到位址列上面。
-
方法:
1、沒有引數時,作為getter,獲取url資訊:
在controller中注入$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):
這裡為什麼要用到$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文字表示的內容,我們需要遵循以下步驟:
- 在html模板中用“ng-bind-html”屬性來繫結一個model(變數);
- 在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
效果: