AngularJS功能最基本的組件之一是服務(Service)。服務爲你的應用提供基於任務的功能。服務能夠被視爲重複使用的執行一個或多個相關任務的代碼塊。javascript
AngularJS服務是單例對象,這意味着只有一個實例被建立過,服務使用AngularJS的依賴注入機制來定義和註冊。css
能夠把服務注入模塊、控制器和其它服務。html
常見的內置服務以下:前端
$http 發送http請求java
$resource 建立一個能夠RESTful服務器端數據源交互對象node
$window 瀏覽器的window元素的jQuery包裝jquery
$document 瀏覽器的document元素的jQuery包裝git
$rootScope 根做用域的訪問angularjs
$rootElement 根元素的訪問github
$cacheFactory 提供鍵/值對放置到對象緩存
$interval 提供對window.setInterval訪問
$timeout 提供對window.setTimeout訪問
$cookies 提供對瀏覽器的cookie的讀寫訪問
$animate 提供動畫鉤子來同時連接到以CSS和JavaScript爲基礎的動畫
引用瀏覽器的window對象。默認瀏覽器的window是全局的根對象。
示例代碼:
<!DOCTYPE html> <!--指定angular管理的範圍--> <html ng-app="app01"> <head> <meta charset="UTF-8"> <title>服務</title> </head> <body> <!--指定控制器的做用範圍--> <form ng-controller="Controller1" name="form1"> </form> <!--引入angularjs框架--> <script src="js/angular146/angular.min.js" type="text/javascript" charset="utf-8"></script> <script type="text/javascript"> //定義模塊,指定依賴項爲空 var app01 = angular.module("app01", []); //定義控制器,指定控制器的名稱,$scope是全局對象 app01.controller("Controller1", ['$scope','$window',function($scope,$win) { $win.alert("調用window服務的alert方法"); }]); </script> </body> </html>
運行結果:
$http服務從AngularJS代碼直接與Web服務器進行交互,底層是經過AJAX實現,與jQuery中$.ajax相似
經過$http封裝後的方法:
delete(url,[config]) 發送謂詞爲delete的異步請求
get(url,[config]) 發送謂詞爲get的異步請求
head(url,[config]) 發送謂詞爲head的異步請求
jsonp(url,[config]) 發送經過jsonp實現跨域的同步請求的請求
post(url,data,[config]) 發送謂詞爲post的異步請求
put(url,data[config]) 發送謂詞爲put的異步請求
基本用法:
$http({method: 'GET', url: '/someUrl'}).
success(function(data, status, headers, config) {
}).
error(function(data, status, headers, config) {
});
詳細的配置以下:
這裏使用NodeJS+Express做爲後臺服務,完成一個簡單的汽車管理功能:
cars.js
var express = require('express'); var router = express.Router(); var _= require('lodash'); var cars=[]; cars.push({id:201701,name:"BMW",price:190,speed:"210km/h",color:"白色"}); cars.push({id:201702,name:"BYD",price:25,speed:"160km/h",color:"紅色"}); cars.push({id:201703,name:"Benz",price:300,speed:"215km/h",color:"藍色"}); cars.push({id:201704,name:"Honda",price:190,speed:"170km/h",color:"黑色"}); cars.push({id:201705,name:"QQ",price:130,speed:"210km/h",color:"白色"}); /* Get */ /*得到全部汽車*/ /*url /cars/*/ router.get('/', function(req, res, next) { res.json(cars); }); /*Get*/ /*得到汽車經過id*/ /*url:/cars/:id */ router.get('/:id', function(req, res, next) { //從路徑中映射參數,轉換成數字 var id=parseInt(req.params.id); var car=_.find(cars,{id:id}); res.json(car); }); /*Post*/ /*添加汽車*/ /*url:/cars/car */ router.post('/car', function(req, res, next) { console.log("收到請求"); var car=req.body; //從請求正文中得到json對象 car.id=_.last(cars).id+1; //將編號修改成最後一輛車的編號+1 cars.push(car); //將汽車對象添加到集合中 res.json(car); //將添加成功的車以json的形式返回 }); /*Put*/ /*修改汽車*/ /*url:/cars/car */ router.put('/car', function(req, res, next) { var car=req.body; //從請求正文中得到json對象 console.log(req.body); var index=_.findIndex(cars,{id:parseInt(car.id)}); //根據id得到車在集合中的下標 cars[index]=car; //替換原對象 //res.json(car); //將修改後的車以json的形式返回 res.send({status:"success", message:"更新成功!"}); }); /*Delete*/ /*刪除汽車*/ /*url:/cars/:id */ router.delete('/id/:id', function(req, res, next) { //得到url中的編號參數 var id=parseInt(req.params.id); var index=_.findIndex(cars,{id:id}); //根據id得到車在集合中的下標 cars.splice(index,1); //在cars數組中刪除下標從index開始的1條數據 res.json(cars); }); module.exports = router;
app.js
var express = require('express'); var path = require('path'); var favicon = require('serve-favicon'); var logger = require('morgan'); var cookieParser = require('cookie-parser'); var bodyParser = require('body-parser'); var index = require('./routes/index'); var users = require('./routes/users'); var pdts = require('./routes/product'); var task = require('./routes/task'); var cars = require('./routes/cars'); var app = express(); //指定視圖引擎爲ejs app.set('views', path.join(__dirname, 'views')); app.set('view engine', 'ejs'); // uncomment after placing your favicon in /public //app.use(favicon(path.join(__dirname, 'public', 'favicon.ico'))); app.use(logger('dev')); app.use(bodyParser.json()); app.use(bodyParser.urlencoded({ extended: false })); app.use(cookieParser()); app.use(express.static(path.join(__dirname, 'public'))); app.all('*', function(req, res, next) { res.header("Access-Control-Allow-Origin", "*"); res.header("Access-Control-Allow-Headers", "content-type"); res.header("Access-Control-Allow-Methods","PUT,POST,GET,DELETE,OPTIONS"); res.header("X-Powered-By",' 3.2.1') res.header("Content-Type", "application/json;charset=utf-8"); next(); }); app.use('/', index); app.use('/users', users); app.use('/pdt', pdts); app.use("/task",task); app.use("/cars",cars); // catch 404 and forward to error handler app.use(function(req, res, next) { var err = new Error('Not Found'); err.status = 404; next(err); }); // error handler app.use(function(err, req, res, next) { // set locals, only providing error in development res.locals.message = err.message; res.locals.error = req.app.get('env') === 'development' ? err : {}; // render the error page res.status(err.status || 500); res.render('error'); }); module.exports = app;
www
#!/usr/bin/env node /** * 依賴模塊,導入 */ var app = require('../app'); var debug = require('debug')('nodejsexpress:server'); var http = require('http'); /** * 從上下文環境中得到監聽端口,若是空則3000 */ var port = normalizePort(process.env.PORT || '3000'); app.set('port', port); /** * 建立Web服務器 */ var server = http.createServer(app); /** * 開始監聽 */ server.listen(port); server.on('error', onError); //指定發生錯誤時的事件 server.on('listening', onListening); //當監聽成功時的回調 /** * 規範化端口 */ function normalizePort(val) { var port = parseInt(val, 10); if (isNaN(port)) { // named pipe return val; } if (port >= 0) { // port number return port; } return false; } /** *錯誤事件監聽 */ function onError(error) { if (error.syscall !== 'listen') { throw error; } var bind = typeof port === 'string' ? 'Pipe ' + port : 'Port ' + port; //錯誤處理 switch (error.code) { case 'EACCES': console.error(bind + ' requires elevated privileges'); process.exit(1); //結束程序 break; case 'EADDRINUSE': console.error(bind + ' is already in use'); process.exit(1); break; default: throw error; } } /** * 當用戶訪問服務器成功時的回調 */ function onListening() { var addr = server.address(); var bind = typeof addr === 'string' ? 'pipe ' + addr : 'port ' + addr.port; debug('Listening on ' + bind); }
示例代碼:
<!DOCTYPE html> <!--指定angular管理的範圍--> <html ng-app="carApp"> <head> <meta charset="UTF-8"> <title>服務</title> <style> * { margin: 0; padding: 0; font-family: microsoft yahei; font-size: 14px; } body { padding-top: 20px; } .main { width: 90%; margin: 0 auto; border: 1px solid #777; padding: 20px; } .main .title { font-size: 20px; font-weight: normal; border-bottom: 1px solid #ccc; margin-bottom: 15px; padding-bottom: 5px; color: blue; } .main .title span { display: inline-block; font-size: 20px; background: blue; color: #fff; padding: 0 8px; background: blue; } a { color: blue; text-decoration: none; } a:hover { color: orangered; } .tab td, .tab, .tab th { border: 1px solid #777; border-collapse: collapse; } .tab td, .tab th { line-height: 26px; height: 26px; padding-left: 5px; } .abtn { display: inline-block; height: 20px; line-height: 20px; background: blue; color: #fff; padding: 0 5px; } .btn { height: 20px; line-height: 20px; background: blue; color: #fff; padding: 0 8px; border: 0; } .abtn:hover, .btn:hover { background: orangered; color: #fff; } p { padding: 5px 0; } fieldset { margin-top: 10px; border: 1px solid #ccc; padding: 5px 10px; } fieldset legend { margin-left: 10px; font-size: 16px; } </style> </head> <body> <!--指定控制器的做用範圍--> <form ng-controller="CarController" class="main"> <h2 class="title"><span>汽車管理</span></h2> <table border="1" width="100%" class="tab"> <tr> <th>序列</th> <th>編號</th> <th>名稱</th> <th>價格</th> <th>顏色</th> <th>速度</th> <th>操做</th> </tr> <tr ng-repeat="c in cars"> <td>{{$index+1}}</td> <td>{{c.id}}</td> <td>{{c.name}}</td> <td>{{c.price}}</td> <td>{{c.color}}</td> <td>{{c.speed}}</td> <td> <a href="#" ng-click="del(c.id)">刪除</a> <a href="#" ng-click="edit(c)">編輯</a> </td> </tr> </table> <fieldset> <legend>汽車詳細</legend> <p> <label for="id">編號</label> <input ng-model="car.id" id="id" ng-readonly="true" /> </p> <p> <label for="name">名稱</label> <input ng-model="car.name" id="name" /> </p> <p> <label for="price">價格</label> <input ng-model="car.price" id="price" /> </p> <p> <label for="color">顏色</label> <input ng-model="car.color" id="color" /> </p> <p> <label for="color">速度</label> <input ng-model="car.speed" id="speed" /> </p> <button ng-click="save()" class="btn">保存</button> <button ng-click="clear()" class="btn">清空</button> </fieldset> </form> <!--引入angularjs框架--> <script src="js/angular146/angular.min.js" type="text/javascript" charset="utf-8"></script> <script type="text/javascript"> //定義模塊,指定依賴項爲空 var carApp = angular.module("carApp", []); //定義控制器,指定控制器的名稱,$scope是全局對象 carApp.controller("CarController", ['$scope', '$http', function($scope, $http) { $scope.cars = []; $scope.save = function() { $http({ url:"http://127.0.0.1:3000/cars/car", data:$scope.car, method: $scope.car.id?"PUT":"POST" }) .success(function(data, status, headers, config) { if($scope.car.id){ alert("修改爲功"); }else{ $scope.cars.push(data); } }) .error(function(data, status, headers, config) { alert(status); }); } $scope.edit=function(c){ $scope.car=c; } $scope.clear=function(){ $scope.car={}; } $http.get("http://127.0.0.1:3000/cars") .success(function(data, status, headers, config) { $scope.cars = data; }) .error(function(data, status, headers, config) { alert(status); }); $scope.del = function(id) { $http.delete("http://127.0.0.1:3000/cars/id/" + id) .success(function(data, status, headers, config) { $scope.cars = data; }) .error(function(data, status, headers, config) { alert(status); }); } }]); </script> </body> </html>
運行結果:
問題:若是後臺服務不是Restful,不接收application/json的參數,則須要修改。Angular的post和put請求Content-Type: application/json默認狀況下,jQuery傳輸數據使用Content-Type: x-www-form-urlencodedand和相似於"foo=bar&baz=moe"的序列,然而AngularJS,傳輸數據使用Content-Type: application/json和{ "foo": "bar", "baz": "moe" }這樣的json序列。請求時修改請求頭部內容:
headers: { 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8' }
$httpParamSerializerJQLike 序列化參數,這個服務須要單獨依賴。
示例:
結果:
AngularJS Batarang是一個顯示AngularJS的scope 層次的Chrome插件,有效的快速查看一個page 中有多少Scope可以幫助咱們快速方便調試AngularJS程序。
AngularJS在內置服務中提供了大量的功能,不過這些服務不必定能知足你的需求,你能夠經過自定義服務解決。能夠將服務看做一個或多個相關任務的一塊可重用代碼。
建立自定義服務有4種主要類型:value,constant,factory,service
定義單個值的簡單服務,模塊的配置階段是不可使用的。
module.value('key',{color:'blue',value:'17'})
也value服務同樣,不過在模塊的配置階段是可使和的。
module.value(「key」,」value」);
提供了把功能實現到服務中的能力。
也能夠把其它服務注入到factory中。
factory是普通function,而service是一個構造器(constructor),這樣Angular在調用service時會用new關鍵字,而調用factory時只是調用普通的function,因此factory能夠返回任何東西,而service能夠不返回
示例代碼:
<!DOCTYPE html> <!--指定angular管理的範圍--> <html ng-app="app01"> <head> <meta charset="UTF-8"> <title>服務</title> </head> <body> <!--指定控制器的做用範圍--> <form ng-controller="Controller1" name="form1"> <p> 半徑:<input ng-model="r" ng-init="r=1"/> </p> <p> 周長:{{circleLength}} </p> <p> 面積:{{circleArea}} </p> </form> <!--引入angularjs框架--> <script src="js/angular146/angular.min.js" type="text/javascript" charset="utf-8"></script> <script type="text/javascript"> //定義模塊,指定依賴項爲空 var app01 = angular.module("app01", []); //value服務 app01.value("i",100); //constant服務 app01.constant("PI",3.14); //factory服務 app01.factory("getArea",['i','PI',function(i,PI){ return function(radius){ return PI*(radius+i)*(radius+i); }; }]) function circleMethod(i,PI,getArea){ this.getLength=function(radius){ return 2*PI*radius; }; this.getSize=function(radius){ return getArea(radius); } } //service服務 app01.service("circleService",circleMethod); //定義控制器,指定控制器的名稱,$scope是全局對象 app01.controller("Controller1", function($scope,circleService) { $scope.$watch("r",function(){ $scope.circleLength=circleService.getLength($scope.r); $scope.circleArea=circleService.getSize($scope.r); }); }); </script> </body> </html>
運行結果:
單頁Web應用因爲沒有後端URL資源定位的支持,須要本身實現URL資源定位。angularjs使用瀏覽器URL "#" 後的字符串來定位資源,區分不一樣的功能模塊。
路由並不是在angularjs核心文件內,你須要另外加入一段腳本 「angular-route.min.js」須要注意的是在建立 「app」 對象是須要填寫對 ngRoute 依賴
示例代碼:
routeTest.html 單頁程序的首頁
<!DOCTYPE html> <html ng-app="app"> <head> <meta charset="utf-8"> <title>路由展現</title> <style> a { color: #333; text-decoration: none; } a:hover { color: orangered; } </style> </head> <body> <p> <a href="#/">返回列表</a> <a href="#/t1">當前時間</a> <hr /> </p> <div ng-view></div> <script src="js/angular146/angular.min.js" type="text/javascript" charset="utf-8"></script> <script src="js/angular146/angular-route.min.js" type="text/javascript" charset="utf-8"></script> <script id="t1" type="text/ng-template"> 當前時間是:{{currentDate}} </script> <script type="text/javascript"> var app = angular.module("app", ['ngRoute']); app.config(function($routeProvider) { $routeProvider.when('/', { controller: 'listController', templateUrl: 'list.html' }); $routeProvider.when('/t1', { controller: 't1Controller', templateUrl: 't1' }); $routeProvider.when('/detail/:id', { controller: 'detailController', templateUrl: 'detail.html' }); $routeProvider.otherwise({ redirectTo: '/' }); }); app.service("dataService", function() { this.list = [{ id: 1, title: '谷歌', url: 'http://www.google.com' }, { id: 2, title: '百度', url: 'http://www.baidu.com' }, { id: 3, title: '必應', url: 'http://www.bing.com' }, { id: 4, title: '搜狗', url: 'http://www.sogou.com' }, { id: 5, title: '雅虎', url: 'http://www.yahoo.cn' }]; this.getEntity = function(id) { var result = null; angular.forEach(this.list, function(obj, index) { if(obj.id == id) { result = obj; } }); return result; } }); app.controller("listController", function($scope, dataService) { $scope.items = dataService.list; }); app.controller("detailController", function($scope, dataService, $routeParams) { $scope.obj = dataService.getEntity($routeParams.id); }); app.controller("t1Controller", function($scope) { $scope.currentDate = new Date().toLocaleString(); }); </script> </body> </html>
列表頁 list.html
<ul ng-repeat="item in items"> <li> <a href="#/detail/{{item.id}}">{{item.title}}</a> </li> </ul>
詳細頁 detail.html:
<fieldset> <legend>詳細信息</legend> <p> 編號:{{obj.id}} </p> <p> 名稱:{{obj.title}} </p> <p> 網址: <a href="{{obj.url}}">{{obj.url}}</a> </p> </fieldset>
運行結果:
示例:
默認狀況JavaScript中對象是傳引用的:
var tom={name:"tom",age:18,height:198}; var tomClone=tom; tomClone.name="superTom"; console.log(tom); console.log(tomClone);
結果:
修改後的示例:
var tom={name:"tom",age:18,height:198}; var tomClone=tom; var tome={} angular.copy(tom,tome); tomClone.name="superTom"; console.log(tom); console.log(tomClone); console.log(tome);
修改後的結果:
jQuery Lite只是jQuery的一個簡化版本,它直接內置於AngularJS中。
支持的jQuery方法以下,但有些方法在功能上並不是徹底同樣。
addClass after append attr bind children clone
contents css data detach empty eq find hasClass
html text on off one parent prepend prop ready
remove removeAttr removeClass removeData replaceWith toggleClass triggerHandler unbind
val wrap
附加事件方法:$destory,controller(name),injector,Scope,isolateScope,inheritedData()
若是須要使用jQuery完整版本的額外功能,那麼能夠在加載AngularJS庫以前引入jQuery庫。
<script src=jquery.min.js>
<script src=angular.min.js>
在自定義指令中link:function(scope,elem,attrs,controller) elem is a jQuery Lite對象
使用時必定要記得將DOM對象轉換成jQuery Lite對象
示例代碼:
<!DOCTYPE html> <!--指定angular管理的範圍--> <html ng-app="app01"> <head> <meta charset="UTF-8"> <title>jQueryLite</title> </head> <body> <!--指定控制器的做用範圍--> <form ng-controller="Controller1" name="form1"> <div id="div1" style="height:100px;background: lightgreen;">jQueryLite</div> </form> <!--引入angularjs框架--> <script src="js/angular146/angular.min.js" type="text/javascript" charset="utf-8"></script> <script type="text/javascript"> //定義模塊,指定依賴項爲空 var app01 = angular.module("app01", []); //定義控制器,指定控制器的名稱,$scope是全局對象 app01.controller("Controller1", ['$scope','$window',function($scope,$win) { var div1=document.querySelector("#div1"); var adiv1=angular.element(div1); adiv1.on("click",function(){ adiv1.css({"background":"lightblue"}).html("Hello "+adiv1.html()); adiv1.off(); }); }]); </script> </body> </html>
運行結果:
zeptojs是一輕量版的jQuery,擁有多數的jQuery功能,但體積要小不少,gzip後只有約9.6k。
倉庫:https://github.com/madrobby/zepto
安裝:npm install zepto
瀏覽器支持:
一、新建4.5版以上的WebAPI項目
二、安裝Microsoft.AspNet.WebApi.Cors
Install-Package Microsoft.AspNet.WebApi.Cors
三、修改app_start目錄下的WebApiConfig.cs文件,增長以下代碼:
//第1*表示域 如www.abc.com //第2*表示容許的頭部 //第3*表示方法(謂詞) config.EnableCors(new EnableCorsAttribute("*", "*", "*"));
四、若是隻想控制某一個控制器,則可使用註解,特性。
[EnableCors("*","*","*")] public class ValuesController : ApiController