一、服務 AngularJS功能最基本的組件之一是服務(Service)。服務為你的應用提供基於任務的功能。服務可以被視為重覆使用的執行一個或多個相關任務的代碼塊。 AngularJS服務是單例對象,這意味著只有一個實例被創建過,服務使用AngularJS的依賴註入機制來定義和註冊。 可以把服務註入 ...
一、服務
AngularJS功能最基本的組件之一是服務(Service)。服務為你的應用提供基於任務的功能。服務可以被視為重覆使用的執行一個或多個相關任務的代碼塊。
AngularJS服務是單例對象,這意味著只有一個實例被創建過,服務使用AngularJS的依賴註入機制來定義和註冊。
可以把服務註入模塊、控制器和其它服務。
1.1、內置服務
常見的內置服務如下:
$http 發送http請求
$resource 創建一個可以RESTful伺服器端數據源交互對象
$window 瀏覽器的window元素的jQuery包裝
$document 瀏覽器的document元素的jQuery包裝
$rootScope 根作用域的訪問
$rootElement 根元素的訪問
$cacheFactory 提供鍵/值對放置到對象緩存
$interval 提供對window.setInterval訪問
$timeout 提供對window.setTimeout訪問
$cookies 提供對瀏覽器的cookie的讀寫訪問
$animate 提供動畫鉤子來同時鏈接到以CSS和JavaScript為基礎的動畫
1.1.1、瀏覽器Window服務($window)
引用瀏覽器的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>
運行結果:
1.1.2、發送http請求服務 ($http)
$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