AngularJS功能最基本的组件之一是服务。服务为拿到应用程序提供基于任务的功能。服务可被视为可重复使用的执行一个或多个相关任务的代码块。AngularJS提供了一些内置的服务,你还可以创建自己的自定义服务。
下面介绍AngularJS服务。 包括一些内置的服务,如用于Web服务器通信的$http。和创建自定义服务的不同用法,以及如何实现它们。
1,了解AngualrJS服务
AngularJS服务是单例对象,这意味着只有一个实例被创建过。服务的目的是提供执行特定任务的一小段简洁的代码。服务即可以如提供一个值定义一样简单,也可以如对一个Web服务器提供完整的HTTP通信一样复杂。
服务为AngularJS应用程序可用的可重复使用的功能提供了一个容器。服务使用AngularJS的依赖注入机制来定义和注册。这可用让你把服务注入模块,控制器和其他服务。
2,使用内置的服务
AngularJS提供了一些内置服务。这些都是自动用依赖注入器注册的,你可用因此利用依赖注入轻松地将它们融入你的AngularJS应用程序。
下表是一些最常见的内置服务,告诉你有哪些功能可利用。
服务 | 说明 |
$animate | 提供动画钩子来同时链接到以CSS和JavaScript为基础的动画 |
$cacheFactory | 提供把键/值对放置到对象缓存中的能力,在那里它们可以被以后使用相同服务的其他代码组件获取 |
$compile | 提供把HTML字符串或DOM对象编译为模板,并制作可以把作用域和模板连接在一起的模板函数的能力 |
$cookies | 提供对浏览器的cookie的读写访问 |
$document | 指定一个对浏览器的window.document元素的jQuery包装的引用 |
$http | 提供一个简单易用的功能来把HTTP请求发送到Web服务器或其他服务 |
$interval | 提供对浏览器的window.location对象交互的能力 |
$locale | 提供由各种AngularJS组件使用的本地化规则 |
$location | 提供与浏览器的window.location交互的能力 |
$resource | 允许你创建一个可以与一个RESTful服务器端数据源进行交互的对象 |
$rootElement | 提供对AngularJS应用程序中的根元素的访问 |
$rootscope | 提供对AngularJS应用程序中根作用域的访问 |
$route | 通过监视$location.url()并把路径映射到现有的路由定义来提供用于控制器和视图的深度连接URL |
$sce | 提供严格的上下文转义函数,用于处理来自不受信任来源的数据 |
$templateCache | 提供把模板从Web服务器读取都缓存供以后使用的能力 |
$timeout | 提供对浏览器的window.setTimeout功能的访问 |
$window | 指定一个对浏览器的window元素的jQuery包装的引用 |
2.1,使用$http服务发送HTTP的GET和PUT请求
你可以利用$http服务,从AngularJS代码直接与Web服务器进行交互。$http服务在底层使用浏览器的XMLHttpRequest对象,但是在AngularJS框架的上下文中使用。
有两种方法使用$http服务的方式。最简单的方式是使用以下内置的对应标准的HTTP请求的快捷方法之一:
- delete(url,[config])
- get(url,[config])
- head(url,[config])
- jsonp(url,[config])
- post(url,data,[config])
- put(url,data,[config])
在这些方法中,url参数是Web请求的URL。可选的config参数是一个JavaScript对象,指定执行请求时要使用的选项。下表列出了可以在config参数中设置的属性。
属性 | 说明 |
method | HTTP方法,比如GET或POST |
url | 被请求的资源的URL |
params | 要被发送的参数。这可以是一个格式为?key1=value1&key2=value2...的字符串,也可以是一个对象,在这种情况下,它变成了一个JSON字符串 |
data | 要作为请求消息的内容 |
headers | 要随请求发送的标头。你可以指定一个对象,它包含要发送的标头名作为其属性。如果该对象中某个属性具有空值,则不发送标头 |
xsrfHeaderName | 要用XSRF令牌填充的HTTP标头的名称 |
xsrfCookieName | 包含XSRF令牌的cookie的名称 |
transformRequest | 被调用来转换/序列化请求标头和正文的函数。该函数接受正文数据作为第一个参数和一个通过名字来获取标头的获取器函数作为第二个参数。例如,function(data,getHeader) |
transformResponse | 被调用来转换/序列化响应标头和正文的函数。该函数接收正文数据作为第一个参数和一个通过名字来获取标头的获取器函数作为第二个参数。例如,function(data,getHeader) |
cache | 一个布尔值。如果为true,则表示将默认$http缓存用于缓存GET响应;否则,如果一个缓存实例是用$cacheFactory建立的,则该缓存实例用于缓存响应。如果为false,并且没有建立$cacheFactory,那么响应不会被缓存 |
timeout | 超时时间,以毫秒为单位。如果到了这个时间,该请求应当被中止 |
withCredentials | 一个布尔值,如果为true,则表示该XHR对象上的withCredentials标志被设置 |
responseType | 期望的响应类型,如json或text |
当你利用$http对象调用请求的方法时,你会取回一个带有promise方法success()和error()的对象。你可以向这些方法传递回调函数,如果请求成功或失败,它会被调用。这些方法接受以下参数。
- data:响应数据
- status:响应状态
- header:响应头
- config:请求配置
下面是在get()请求上实现success()和error()方法的简单例子:
$http({method:'GET',url:'/myUrl'}). success(function(data,status,headers,config){ //处理成功情况 }). error(funciton(data,status,headers,config){ //处理失败情况 });
如下所示的3个代码清单实现了一个端到端的AngularJS/Node.js Web应用程序,它允许用户初始化天的列表,并从列表中删除天。这个例子很简陋,所以它的代码很容易理解,但它结合了GET和POST请求以及错误处理的例子。
第一个代码清单node_server.js,实现了Node.js的web服务器,它处理GET路由/reset/days和post路由/remove/day。如果在列表中只有不到两天,/remove/day路由将返回一个HTTP错误。
node_server.js:实现支持AngularJS控制器的GET和POST路由的Express服务器
var express = require('express'); var bodyParser = require('body-parser'); var app = express(); app.use('/',express.static('./static')). use('/images',express.static('../images')). use('/lib',express.static('../lib')); app.use(bodyParser()); var days = ['Monday','Tuesday','Wednesday','Thursday','Friday']; var serviceDays = days.slice(0); app.get('/reset/days',function(req,res){ serviceDays = days.slice(0); res.json(serviceDays); }); app.post('/remove/day',function(req,res){ if(serviceDays.length > 2){ serviceDays.splice(serviceDays.indexOf(req.body.day),1); console.log(days); res.json(serviceDays); }else{ res.json(400,{msg:'you must leave 2 days'}); } }); app.listen(80);
service_http.js:实现利用$http服务与web服务器交互dAngularJS控制器
angular.module('myApp',[]). controller('myController',['$scope','$http',function($scope,$http){ $scope.day = []; $scope.status = ""; $scope.removeDay = function(daleteDay){ $http.post('/remove/day',{day:deleteDay}). success(function(data,status,headers,config){ $scope.days = data; }). error(function(data,status,headers,config){ $scope.status = data.msg; }); }; $scope.resetDays = function(){ $scope.status = ""; $http.get('/reset/days'). success(function(data,status,headers,config){ $scope.days = data; }). error(function(data,status,headers,config){ $scope.status = data; }); }; }]);
service_http.html:一个实现链接到Web服务器的数据的指令的AngularJS模板
<!doctype html> <html ng-app="myApp"> <head> <title>AngularJS $http Service</title> <style>span{color:red;}</style> </head> <body> <div ng-controller="myController"> <h2>$http Service</h2> <input type="button" ng-click="resetDays()" value="Initialize Days" /> {{status}} <h3>Days Available</h3> <div ng-repeat="day in days"> {{day}} [<span ng-click="removeDay(day)">remove</span>] </div> </div> <script src="js/angular.js"></script> <script src="js/service_http.js"></script> </body> </html>
2.2,使用$cacheFactory服务
$cacheFactory服务提供了一个非常方便的存储库用于暂时存储数据的键/值对。因为$cacheFactory是一个服务,所以它可供多个控制器和其他AngularJS组件使用。
在创建$cacheFactory服务时,你可以指定一个options对象,它包含capacity属性,例如{capacity:5}。通过此capacity设置,则限制了在缓存中行的最大数量是5.当一个条目被添加时,最早的项目被删除。如果不指定容量,缓存会持续增长。
下面的代码清单演示了在Module对象上实现一个$cacheFactory,然后从两个1的控制器访问它的一个基本的例子:
var app = angular.module('myApp',[]); app.factory('myCache',function($cacheFactory){ return $cacheFactory('mycache',{capacity:5}); }); app.controller('myController',['$scope','MyCache',function($scope,cache){ cache.put('myValue',55); }]); app.controller('myController2',['$scope','myCache',function($scope,cache){ $scope.value=cache.get('myValue'); }]);
2.3,使用$window服务实现浏览器警报
$window服务为浏览器的window对象提供了一个jQuery封装,这允许你如同通常从JavaScript那样反问window对象。为了说明这一点,下面的代码使用window对象上的alert()方法来弹出一个浏览器警报。警报的信息从浏览器的window对象的$window.screen.availWidth和$window.screen.availHeight属性获取数据:
var app = angular.module('myApp',[]); app.controller('myController',['$scope','$window',function($scope,window){ window.screen.availWidth + "X" + window.screen.availHeight; }]);
2.4,使用$cookieStore服务与浏览器cookie交互
AngularJS提供了获取和设置cookie的一对服务:$cookie和$cookieStore。cookie在浏览器中提供临时存储,并即使在用户离开网页或关闭浏览器后也继续存在。
$cookie服务允许你利用句点表示法莱获取和改变字符串的cookie值。例如,下面的例子检索名为appCookie的一个cookie的值,然后改变它:
var cookie = $cookie.appCookie; $cookie.appCookie = 'new Value';
$cookieStore服务提供get(),put()和remove()函数来获取,设置和删除cookie。$cookieStore服务的一个很好的功能就是它在设置JavaScript对象值之前把它们序列化为JSON字符串,然后它在获取它们时将其反序列化回对象。
service_cookies.js:实现利用$cookieStore服务与浏览器的cookie交互的AngularJS控制器
var app = angular.module('myApp',['ngCookies']); app.controller('myController',['$scope','$cookieStore',function($scope,cookieStore){ $scope.favCookie = ''; $scope.myFavCookie = ''; $scope.setCookie = function(){ if($scope.favCookie === 'None'){ cookieStore.remove('myAppCookie'); }else{ cookieStore.put('myAppCookie',{flavor:$scope.favCookie}); } $scope.myFavCookie = cookieStore.get('myAppCookie'); }; }]);
service_cookies.html:实现单选按钮来设置cookie值的AngularJS模板
<!doctype html> <html ng-app="myApp"> <head> <title>AngularJS $cookie Service</title> </head> <body> <div ng-controller="myController"> <h3>Favorite Cookie</h3> <input type="radio" value="Chocolate Chip" ng-model="favCookie" ng-change="setCookie()"> Chocolate Chip</value><hr/> <input type="radio" value="Oatmeal" ng-model="favCookie" ng-change="setCookie()"> Oatmeal</value><hr/> <input type="radio" value="Frosted" ng-model="favCookie" ng-change="setCookie()"> Frosted</value><hr/> <hr>Cookies:{{myFavCookie}} </div> <script src="js/angular.js"></script> <script src="js/angular-cookies.js"></script> <script src="js/service_cookies.js"></script> </body> </html>
2.5,使用$interval和$timeout实现定时器
AngularJS的$interval()和$timeout()服务,使你能够把代码的执行延迟一定量的时间。这些服务与JavaScript的setInterval和setTimeout的功能交互,但在AngularJS框架内进行。
$interval()和$timeout()服务使用一下语法:
$interval(callback,delay,[count],[invokeApply]); $timeout(callback,delay,[invokeApply]);
它们的参数含义如下。
- callback:在延迟已过期时执行
- delay:指定执行回调函数之前等待的毫秒数
- count:指示时间间隔的重复次数
- invokeApply:一个布尔值,如果为true,则导致该函数只在AngularJS事件循环的$apply()块中执行。默认值为true。
当你调用$interval()和timeout()方法时,它们返回一个promise对象,你可以用它来取消超时时间或时间间隔。要取消现有的$timeout或$interval,可调用cancel()方法。例如:
var myInterval = $interval(function(){$scope.seconds++;},1000,10,true); ... $interval.cancel(myInterval);
如果使用$interval或$timeout建立超时时间或时间间隔,则必须在scope(作用域)或elements(元素)指令被销毁时显示地使用cancel()销毁它们。做到这一点最简单的方法就是对$destory添加一个监听器。例如:
$scope.$on('$destory',function(){ $scope.cancel(myInterval); });
2.6,使用$animate服务
$animate服务提供动画检测挂钩,在执行进入,离开和移动DOM操纵以及addClass和removeClass操纵时,可以使用它们。你可以通过CSS类名或通过JavaScript中的$animate服务使用这些挂钩。
要实现动画,你需要为要以动画方式显示的元素添加一个支持动画的指令。下表列出了支持动画的指令和它们支持的动画的事件类型。
指令 | 说明 |
ngRepeat | 支持enter,leave和move事件 |
ngView | 支持enter和leave事件 |
ngInclude | 支持enter和leave事件 |
ngSwitch | 支持enter和leave事件 |
ngIf | 支持enter和leave事件 |
ngClass | 支持addClass和removeClass事件 |
ngShow | 支持addClass和removeClass事件 |
ngHide | 支持addClass和removeClass事件 |
在CSS中实现动画
要在CSS中实现动画,你需要在摇椅动画方式显示的元素中包含ngClass指令。AngularJS使用ngClass值作为将要在播放动画期间要从元素中添加和删除额外的CSS类的根名称。
动画事件将在具有一个ngClass指令的元素上被调用。下表列出了在播放动画过程中被添加和删除的类。
类 | 说明 |
ng-animate | 当一个事件被添加时触发 |
ng-animate-active | 当动画开始并触发CSS转化时添加 |
<super>-ng-move | 当move事件被触发时添加 |
<super>-ng-move-active | 当move事件开始并触发CSS转换时添加 |
<super>-ng-leave | 当leave事件被触发时添加 |
<super>-ng-leave-active | 当leave动画开始并触发CSS转换时添加 |
<super>-ng-enter | 当enter事件被触发时添加 |
<super>-ng-enter-active | 当enter动画开始并触发CSS转换时添加 |
<super>-ng-add | 当addClass事件被触发时添加 |
<super>-ng-add-active | 当addClass动画开始并触发CSS转换时添加 |
<super>-ng-remove | 当removeClass事件被触发时添加 |
<super>-ng-remove-active | 当removeClass动画开始并触发CSS转换时添加 |
要实现基于CSS的动画,所有你需要做的就是为上表列出的附加类添加相应的CSS转换代码。为了说明这一点,下面的代码片段实现了为名为.img-fade的用户自定义的类添加类和删除类转换,这用2秒的时间以动画方式把图像的不透明度改为0.1:
.ing-fade-add,.img-fade-remove{ -webkit-transition:all ease 2s; -moz-transition:all ease 2s; -o-transition:all ease 2s; transition:all ease 2s; } .img-fade,.img-fade-add.img-fade-add-active{ opacity:.1; }
请注意,转换被添加到.img-fade-add和.img-fade-remove类,但实际的类定义被应用到.img-fade。你还需要用类定义.img-fade-add.img-fade-add-active来设置转换的结束状态。
在JavaScript中实现动画
实现AgularJS CSS动画是很简单的,但是你也可以在JavaScript中使用jQuery实现动画。JavaScript动画对你的动画提供更直接的控制。此外,JavaScript的动画不需要浏览器支持CSS3.
要在JavaScript中实现动画,你需要在angular.js库被加载之前先在模板中包含jQuery库。
你还需要在应用程序Module对象定义中包含ngAnimate依赖。例如:
var app = angular.module('myApp',['ngAnimate']);
然后,你可以使用module对象的animate()方法来实现动画。animate()方法返回一个对象,它提供了enter,leave,move,addClass和removeClass事件的处理函数。这些功能会把需要播放动画的元素作为第一个参数传入。然后,你就可以使用jQuery的animate()方法来以动画方式显示一个元素。
jQuery的animate()方法使用以下语法,其中cssProperties是CSS属性变化的对象,duration以毫秒为单位指定,easing是减缓的方法,而callback是在动画完成时执行的函数:
animate(cssProperties,[duration],[easing],[callback])
例如,下面的代码通过把不透明度设置为0以动画方式添加fadeClass类到一个元素:
app.animation('.fadeClass',function(){ return{ addClass:function(element,className,done){ jQuery(element).animate({opacity:0},3000); } }; });