http://blog.csdn.net/vitalemon__/article/details/52163866 链接地址
AngularJS常用服务($http、$location、$sce等)
这篇博客,只是简单地说下AngularJS中的常用的系统(自带)服务。如果逻辑不清晰,就当作是一个参考手册吧,来查查用法什么的。
另外,附上一些参考网站:
AngularJS手册:http://man.hubwiz.com/manual/AngularJS(汇智网)
AngularJS常用服务:https://docs.angularjs.org/api/ng/service(AngularJS官方文档)
一、$http
$http是对Ajax(XHR)的封装。这里介绍3种用法。
1、GET请求的用法:
$http.get(url)
.success(function (data) {
// 这里的data是一个object,是我们想要的数据部分,不包含状态码等
// 成功的回调 }).error(function (err) { // 出错的回调 });
- $http.get(url) .success(function (data) { // 这里的data是一个object,是我们想要的数据部分,不包含状态码等 // 成功的回调 }).error(function (err) { // 出错的回调 });
2、POST请求的用法也差不多,只是多了参数:
var url = "...";
var postData = {
id: "123",
token: "x1234q3412fwdfw3r23" }; $http.post(url, postData) .success(function (data) { // 成功的回调 }).error(function (err) { // 出错的回调 });
- var url = "..."; var postData = { id: "123", token: "x1234q3412fwdfw3r23" }; $http.post(url, postData) .success(function (data) { // 成功的回调 }).error(function (err) { // 出错的回调 });
题外话:这里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); });
- // 在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); });
此外,put、delete等,可以直接看手册,这里就不多说了。而且,格式都是差不多的:
二、$location(配合$anchorScroll)
-
简介:使用$location可以得到当前页面url的参数。用户对于Url做出的改变,会通知到$location中,而$location对Url的一些操纵也会反映到地址栏上面。
-
方法:
1、没有参数时,作为getter,获取url信息:
举个例子,以我测试的代码打开的url:
http://localhost:63342/test/templates/demo01.html#/hello?name=jk&age=10#helloworld
在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
- // 假定原来的完整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
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>
- <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>
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()来重新定位 } } }]);
- 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()来重新定位 } } }]);
效果(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');
(2)添加kv对,put方法:
cache.put(key, value);
(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); // 错误!不能再访问该缓存,要重新生产一个实例出来
四、$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
效果: