Node.js開發入門—使用AngularJS內置服務
在上一篇,“AngularJS簡單示例”中演示了一個非常簡單的使用Angular的小demo,那篇已經太長,原本要介紹的一些內容只好單另開篇了。這些內容,就是如何使用Angular服務。
我們還是基于“AngularJS簡單示例”中的示例來改造一下。新的示例,能從Node.js+Express構造的服務器上獲取管理菜單。為了實現這個,需要做幾部分改造:
-
服務器提供adminMenu的下載功能,需要修改app.js,處理路由
</li> -
修改Angular實現的控制器x-controller,使用$http服務從Web服務器下載adminMenu
</li> -
修改HTML模板,觸發下載動作
</li> </ul>修改app.js
首先要將app.js文件的編碼格式改一下,改成UTF8,因為我在代碼里直接硬寫入了中文。代碼如下:
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 routes = require('./routes/index'); var users = require('./routes/users'); var app = express(); // view engine setup app.set('views', path.join(__dirname, 'views')); app.set('view engine', 'jade'); // 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.use('/', routes); app.use('/users', users); app.get('/adminMenu', function(req, res, next){ var menus = [ { text: "系統管理", enabled: true, subMenus:[ { text: "用戶管理", enabled: true, action:"/admin/addUser" }, { text: "角色管理", enabled: true, action:"/role" }, { text: "權限管理", enabled: true, action:"/access" } ] }, { text: "內容管理", enabled: false, subMenus:[ { text: "直播流監控", enabled: true, action:"/stream-monitor" }, { text: "預約管理", enabled: true, action:"/book-mgr" } ] }, { text: "推送管理", enabled: true, subMenus:[ { text: "推送列表", enabled: true, action:"/push-list" }, { text: "新增推送", enabled: false, action:"/add-push" } ] } ]; res.status(200).send(menus); }); // 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 handlers // development error handler // will print stacktrace if (app.get('env') === 'development') { app.use(function(err, req, res, next) { res.status(err.status || 500); res.render('error', { message: err.message, error: err }); }); } // production error handler // no stacktraces leaked to user app.use(function(err, req, res, next) { res.status(err.status || 500); res.render('error', { message: err.message, error: {} }); }); module.exports = app;
從“app.get(‘/adminMenu’”這行開始,我添加了響應/adminMenu的代碼。同時設置了部分菜單項的enabled屬性,讓從服務器獲取的菜單與“Angular簡單示例”中來自本地的菜單不同。
觸發下載
我修改了admin.html文檔,使用了ng-init指令來執行作用域內的init方法。在init方法內,使用$http服務下載管理菜單。
新的html文件被我重命名為admin2.html,依然放在public目錄下。相比admin.html,admin2.html只改動了兩行代碼:
<body> <div class="x-view-full" ng-controller="x-controller" ng-init="init()"> ...... <script src="/javascripts/admin2.js"></script> </body>
ng-init指令允許我們在當前作用域內執行一個JS表達式。
使用$http服務下載管理菜單
我修改了admin.js,重名為admin2.js,放在public/javascripts目錄下。admin2.js內容如下:
angular.module('x-admin', []). controller('x-controller', ['$scope', '$http', function ($scope, $http) { $scope.currentUser="ZhangSan"; $scope.content = '/welcome.html'; $scope.menus = []; $scope.init = function(){ $http.get("/adminMenu") .success(function(data, status, headers, config){ console.log("got menus"); $scope.menus = data; }) .error(function(data, status, headers, config){ console.log("got menus failed. status - " + status); }); }; $scope.setContent = function(action){ console.log(action); $scope.content=action; }; }]);
我為作用域定義了init方法,供HTML文檔內的ng-init指令調用。在init方法內,使用了$http服務來下載adminMenu。
我給success方法提供了回調,當下載成功后,修改作用域的menus屬性,把從/adminMenu下載到的json數組直接賦值給menus屬性。從Node.js后端到Angular前端,json對json,無需轉換,酸爽!
$http的get方法的參數是URI,如示例中的用法,你可以略去域名部分。你也可以使用完整的URL,比如 http://localhost :3000/adminMenu,效果是一樣一樣一樣的。
$http服務內部使用了瀏覽器的XMLHttpRequest(XHR)對象。
好啦,最終,你在瀏覽器內訪問“ http://localhost :3000/admin2.html”,效果可能是這樣的:
//view-angular-admin2.png
另一種寫法
其實呢,這個簡單的示例,可以不用ng-init指令,這樣更簡單,admin2.html與admin.html就只有一點差異:將HTML引用的admin.js修改為admin2.js。然后呢,修改一下admin2.js,直接在控制器的構造函數內開始下載即可。新的代碼如下:
angular.module('x-admin', []). controller('x-controller', ['$scope', '$http', function ($scope, $http) { $scope.currentUser="ZhangSan"; $scope.content = '/welcome.html'; $scope.menus = []; $http.get("http://localhost:3000/adminMenu") .success(function(data, status, headers, config){ console.log("got menus"); $scope.menus = data; }) .error(function(data, status, headers, config){ console.log("got menus failed. status - " + status); }); $scope.setContent = function(action){ console.log(action); $scope.content=action; }; }]);
更多的Angular服務
Angular提供了很多內置服務,想在控制器內使用的話,在控制器構造函數的參數里直接寫上服務的名字,Angular自動會為我們完成依賴注入。
angular.module('x-admin', []). controller('x-controller', ['$scope', '$http', function ($scope, $http)
上面的代碼,x-controller的構造函數依賴scope和http,如果想使用其他的服務,比如$window,可以改成下面這樣:
angular.module('x-admin', []). controller('x-controller', ['$scope', '$http', '$window', function ($scope, $http, $window)
這種寫法太繁瑣,多輸入好些字符,我還是喜歡這樣:
controller('x-controller', function ($scope, $http, $interval) {