這次帶給大家Nodejs用Angular創建單頁應用,Nodejs用Angular創建單頁應用的注意事項有哪些,下面就是實戰案例,一起來看一下。
在根目錄下新建一個app_client,用來專門放單頁相關的程式碼。不要忘記設定為靜態:
app.use(express.static(path.join(dirname, 'app_client')))
Angular路由
在SPA應用程式中,頁間的切換並不會每次都向背景發送求請求。這一節將路由移到客戶端,但保留母版頁(layout.jade),其他視圖用Angular實作。為此先在控制器中新建一個angularApp方法。
module.exports.angularApp = function (req, res) { res.render('layout', { title: 'ReadingClub' }); };
設定路由
router.get('/', ctrlOthers.angularApp);
剩下的Express路由是多餘的了,你可以刪除或註解。為避免頁面重新加載,Angular的預設做法就是在url中加一個#號。 #號一般是用來當錨,來定位頁面上的點,Angular用來存取應用程式中的點。例如在Express中,訪問about頁面:
/about
在Angular中,url會變成
/#/about
不過這個#號也是可以拿掉的,畢竟看起來不是那麼直觀,這個在下一節講。
舊版的Angular函式庫是包含路由模組的,但是現在是作為一個外部依賴文件,可以自己維護。所以先需要下載並加入到專案中。 https://code.angularjs.org/1.2.19/
下載angular-route.min.js和angular-route.min.js.map,並在app_client下建立一個app.js
在layout.jade 中加入
script(src='/angular/angular.min.js') script(src='/lib/angular-route.min.js') script(src='/app.js')
使用路由前需要設定模組依賴,要注意的是路由的檔案名稱是angular-route,但實際模組名稱是ngRoute。在app_client/app.js 下:
angular.module('readApp', ['ngRoute']);
ngRoute模組會產生一個$routeProvider對象,可以用來傳遞配置函數,也就是我們定義路由的地方:
function config($routeProvider) { $routeProvider .when('/', {}) .otherwise({ redirectTo: '/' }); } angular .module('readApp') .config(['$routeProvider', config]);
回顧先前的$ http,$scope,service 以及現在的$routeProvider 出現在函數參數的時候,Angular會自動為我們取得實例,這就是Angular的依賴注入機制;config方法定義了路由。而目前這個路由沒有做多少活,但語法很直觀,當URL是'/'時,也就是訪問主頁時什麼都不做。而當是別的URL訪問時就跳到首頁。接下來我們讓這個路由幹點活。
Angular 視圖
先在app_client資料夾下建立一個home資料夾,用來放置主頁的一些檔案。但是目前首頁都還是jade視圖,我們需要將其轉換為html,因此先創建一個home.view.html:
<p> </p><p> </p><p><a>全部</a><a>读书</a><a>书评</a><a>求书</a><a>求索</a></p> <p> <img src="/static/imghwm/default1.png" data-src="https://img.php.cn/upload/article/000/061/021/e5289cf85d1925a677e4c8b5ebde7822-1.png?x-oss-process=image/resize,p_40" class="lazy" alt="Nodejs用Angular創建單頁應用" ><span><i>{{topic.commentCount}}</i><i>/</i><i>{{topic.visitedCount}}</i></span> <span>{{topic.type}}</span><a>{{topic.title}}</a> <span>{{topic.createdOn}}</span><a>{{topic.author}}</a> </p> <p> </p><p> </p><p>{{user.userName}}</p>
因為還沒有數據,所以這個html片段什麼也不會做。而接下來就是告訴Angular模組,訪問主頁的時候加載這個視圖,這透過templateUrl 實現,修改路由:
function config($routeProvider) { $routeProvider .when('/', { templateUrl: 'home/home.view.html' }) .otherwise({ redirectTo: '/' }); }
但這只是提供了一個模板地址,Angular從哪裡開始替換呢,像Asp. Net MVC中有一個@RenderBody的標記,在jade中是block content。這就需要用到ngRoute模組中的一個指令:ng-view。被標記的元素會被Angular當成容器來切換視圖。我們不妨就加在block content的上方:
#bodycontent.container p(ng-view) block content
控制器
有了路由和視圖,還需要控制器.同樣在home資料夾下創建一個home.controller.js文件,先還是使用靜態資料。經過了上一節,這個部分是輕車熟路。
angular .module('readApp') .controller('homeCtrl', homeCtrl);
function homeCtrl($scope) { $scope.data = topics; $scope.user = { userName: "stoneniqiu", }; }
再修改路由:
function config($routeProvider) { $routeProvider .when('/', { templateUrl: 'home/home.view.html', controller: 'homeCtrl', }) .otherwise({ redirectTo: '/' }); }
這時候訪問頁面,出來資料了。 所以不管是Asp.net MVC,Express還是Angular,MVC模式的想法是一致的,要求先到達路由,路由負責轉送控制器,控制器拿到資料然後渲染視圖。
和上一節不同的是,沒有在頁面上使用ng-controller 指令了,而是在路由裡面指定。
controllerAs
Angular提供了一个创建视图模型的方法来绑定数据,这样就不用每次直接修改$scope 对象,保持$scope 干净。
function config($routeProvider) { $routeProvider .when('/', { templateUrl: 'home/home.view.html', controller: 'homeCtrl', controllerAs: 'vm' }) .otherwise({ redirectTo: '/' }); }
红色代码表示启用controllerAs语法,对应的视图模型名称是vm。这个时候Angular会将控制器中的this绑定到$scope上,而this又是一个上下文敏感的对象,所以先定义一个变量指向this。controller方法修改如下
function homeCtrl() { var vm = this; vm.data = topics; vm.user = { userName: "stoneniqiu", }; }
注意我们已经拿掉了$scope参数。然后再修改下视图,加上前缀vm
<p> </p><p> </p><p><a>全部</a><a>读书</a><a>书评</a><a>求书</a><a>求索</a></p> <p>{{ vm.message }}</p> <p> <img src="/static/imghwm/default1.png" data-src="https://img.php.cn/upload/article/000/061/021/e5289cf85d1925a677e4c8b5ebde7822-2.png?x-oss-process=image/resize,p_40" class="lazy" alt="Nodejs用Angular創建單頁應用" ><span><i>{{topic.commentCount}}</i><i>/</i><i>{{topic.visitedCount}}</i></span> <span>{{topic.type}}</span><a>{{topic.title}}</a> <span>{{topic.createdOn}}</span><a>{{topic.author}}</a> </p> <p> </p><p> </p><p>{{vm.user.userName}}</p>
service:
因为服务是给全局调用的,而不是只服务于home,所以再在app_clinet下新建一个目录:common/services文件夹,并创建一个ReadData.service.js :
angular .module('readApp') .service('topicData', topicData);function topicData ($http) { return $http.get('/api/topics'); };
直接拿来上一节的代码。注意function写法, 最好用function fool()的方式,而不要var fool=function() 前者和后者的区别是前者的声明会置顶。而后者必须写在调用语句的前面,不然就是undefined。修改layout
script(src='/app.js') script(src='/home/home.controller.js') script(src='/common/services/ReadData.service.js')
相应的home.controller.js 改动:
function homeCtrl(topicData) { var vm = this; vm.message = "loading..."; topicData.success(function (data) { console.log(data); vm.message = data.length > 0 ? "" : "暂无数据"; vm.data = data; }).error(function (e) { console.log(e); vm.message = "Sorry, something's gone wrong "; }); vm.user = { userName: "stoneniqiu", }; }
这个时候页面已经出来了,但是日期格式不友好。接下来添加过滤器和指令
filter&directive
在common文件夹创建一个filters目录,并创建一个formatDate.filter.js文件,同上一节一样
angular .module('readApp') .filter('formatDate', formatDate);function formatDate() { return function (dateStr) { var date = new Date(dateStr); var d = date.getDate(); var monthNames = ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12"]; var m = monthNames[date.getMonth()]; var y = date.getFullYear(); var output = y + '/' + m + '/' + d; return output; }; };
然后在common文件夹下新建一个directive文件夹,再在directive目录下新建一个ratingStars目录。ratingStars指令会在多个地方使用,它包含一个js文件和一个html文件,将上一节的模板文件复制过来,并命名为:ratingStars.template.html。然后新建一个ratingStars.directive.js文件,拷贝之前的指令代码,并改造两处。
angular .module('readApp') .directive('ratingStars', ratingStars);function ratingStars () {return { restrict: 'EA',scope: { thisRating : '=rating'},templateUrl: '/common/directive/ratingStars/ratingStars.template.html'}; }
EA表示指令作用的范围,E表示元素(element),A表示属性(attribute),A是默认值。还C表示样式名(class),M表示注释(comment), 最佳实践还是EA。更多知识可以参考这篇博客 Angular指令详解
因为还没有创建booksController,先用topic.commentCount来测试ratingStars指令,并记得在layout下添加引用。
<p> <img src="/static/imghwm/default1.png" data-src="https://img.php.cn/upload/article/000/061/021/e5289cf85d1925a677e4c8b5ebde7822-2.png?x-oss-process=image/resize,p_40" class="lazy" alt="Nodejs用Angular創建單頁應用" ><span><i>{{topic.commentCount}}</i><i>/</i><i>{{topic.visitedCount}}</i></span> <small></small> <span>{{topic.type}}</span><a>{{topic.title}}</a> <span>{{topic.createdOn | formatDate}}</span><a>{{topic.author}}</a> </p>
这个时候效果已经出来了。
有哪些优化?
这一节和上一节相比,展现的内容基本没有变化,但组织代码的结构变得更清晰好维护了,但还是不够好,比如layout里面我们增加了过多的js引用。这也是很烦的事情。所以我们可以做一些优化:
1.减少全局变量
第一点,在团队开发的时候要尽量减少全局变量,不然容易混淆和替换,最简单的办法就是用匿名函数包裹起来:
(function() { //....})();
被包裹的内容会在全局作用域下隐藏起来。而且在这个Angular应用也不需要通过全局作用域关联,因为模块之间都是通过angular.module('readApp', ['ngRoute'])连接的。controller、service、directive这些js都可以处理一下。
2.减少JavaScript的尺寸
我们可以让js最小化,但有一个问题,在controller中的依赖注入会受影响。因为JavaScript在最小化的时候,会将一些变量替换成a,b,c
function homeCtrl ($scope, topicData, otherData)
会变成:
function homeCtrl(a,b,c){
这样依赖注入就会失效。这个时候怎么办呢,就要用到$inject ,$inject作用在方法名称后面,等于是声明当前方法有哪些依赖项。
homeCtrl.$inject = ['$scope', 'topicData', 'otherData'];function homeCtrl ($scope, topicData, otherData) {
$inject数组中的名字是不会在最小化的时候被替换掉的。但记住顺序要和方法的调用顺序一致。
topicData.$inject = ['$http'];function topicData ($http) { return $http.get('/api/topics'); };
做好了这个准备,接下来就可以最小化了
3.减少文件下载
在layout中我们引用了好几个js,这样很烦,可以使用UglifyJS 去最小化JavaScript文件。 UglifyJS 能将Angular应用的源文件合并成一个文件然后压缩,而我们只需在layout中引用它的输出文件即可。
安装:
然后在根目录/app.js中引用
var uglifyJs = require("uglifyjs");var fs = require('fs');
接下来有三步
1.列出需要合并的文件
2.调用uglifyJs 来合并并压缩文件。
3.然后保存在Public目录下。
在/app.js下var一个appClientFiles数组,包含要压缩的对象。然后调用uglifyjs.minify方法压缩,然后写入public/angular/readApp.min.js
var appClientFiles = [ 'app_client/app.js', 'app_client/home/home.controller.js', 'app_client/common/services/ReadData.service.js', 'app_client/common/filters/formatDate.filter.js', 'app_client/common/directive/ratingStars/ratingStars.directive.js'];var uglified = uglifyJs.minify(appClientFiles, { compress : false }); fs.writeFile('public/angular/readApp.min.js', uglified.code, function (err) { if (err) { console.log(err); } else { console.log('脚本生产并保存成功: readApp.min.js'); } });
最后修改layout:
script(src='/angular/readApp.min.js') //script(src='/app.js') //script(src='/home/home.controller.js') //script(src='/common/services/ReadData.service.js') //script(src='/common/filters/formatDate.filter.js') //script(src='/common/directive/ratingStars/ratingStars.directive.js')
这里选择注释而不是删掉,为了便于后面的调试。但如果用nodemon启动,它会一直在重启。因为生产文件的时候触发了nodemon重启,如此循环。所以这里需要一个配置文件告诉nodemon忽略掉这个文件的改变。在根目录下新增一个文件nodemon.json
{ "verbose": true, "ignore": ["public//angular/readApp.min.js"] }
这样就得到了一个min.js 。原本5个文件是5kb,换成min之后是2kb。所以这个优化还是很明显的。
相信看了本文案例你已经掌握了方法,更多精彩请关注php中文网其它相关文章!
推荐阅读:
以上是Nodejs用Angular創建單頁應用的詳細內容。更多資訊請關注PHP中文網其他相關文章!

是的,JavaScript的引擎核心是用C語言編寫的。 1)C語言提供了高效性能和底層控制,適合JavaScript引擎的開發。 2)以V8引擎為例,其核心用C 編寫,結合了C的效率和麵向對象特性。 3)JavaScript引擎的工作原理包括解析、編譯和執行,C語言在這些過程中發揮關鍵作用。

JavaScript是現代網站的核心,因為它增強了網頁的交互性和動態性。 1)它允許在不刷新頁面的情況下改變內容,2)通過DOMAPI操作網頁,3)支持複雜的交互效果如動畫和拖放,4)優化性能和最佳實踐提高用戶體驗。

C 和JavaScript通過WebAssembly實現互操作性。 1)C 代碼編譯成WebAssembly模塊,引入到JavaScript環境中,增強計算能力。 2)在遊戲開發中,C 處理物理引擎和圖形渲染,JavaScript負責遊戲邏輯和用戶界面。

JavaScript在網站、移動應用、桌面應用和服務器端編程中均有廣泛應用。 1)在網站開發中,JavaScript與HTML、CSS一起操作DOM,實現動態效果,並支持如jQuery、React等框架。 2)通過ReactNative和Ionic,JavaScript用於開發跨平台移動應用。 3)Electron框架使JavaScript能構建桌面應用。 4)Node.js讓JavaScript在服務器端運行,支持高並發請求。

Python更適合數據科學和自動化,JavaScript更適合前端和全棧開發。 1.Python在數據科學和機器學習中表現出色,使用NumPy、Pandas等庫進行數據處理和建模。 2.Python在自動化和腳本編寫方面簡潔高效。 3.JavaScript在前端開發中不可或缺,用於構建動態網頁和單頁面應用。 4.JavaScript通過Node.js在後端開發中發揮作用,支持全棧開發。

C和C 在JavaScript引擎中扮演了至关重要的角色,主要用于实现解释器和JIT编译器。1)C 用于解析JavaScript源码并生成抽象语法树。2)C 负责生成和执行字节码。3)C 实现JIT编译器,在运行时优化和编译热点代码,显著提高JavaScript的执行效率。

JavaScript在現實世界中的應用包括前端和後端開發。 1)通過構建TODO列表應用展示前端應用,涉及DOM操作和事件處理。 2)通過Node.js和Express構建RESTfulAPI展示後端應用。

JavaScript在Web開發中的主要用途包括客戶端交互、表單驗證和異步通信。 1)通過DOM操作實現動態內容更新和用戶交互;2)在用戶提交數據前進行客戶端驗證,提高用戶體驗;3)通過AJAX技術實現與服務器的無刷新通信。


熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

EditPlus 中文破解版
體積小,語法高亮,不支援程式碼提示功能

Dreamweaver Mac版
視覺化網頁開發工具

記事本++7.3.1
好用且免費的程式碼編輯器

MantisBT
Mantis是一個易於部署的基於Web的缺陷追蹤工具,用於幫助產品缺陷追蹤。它需要PHP、MySQL和一個Web伺服器。請查看我們的演示和託管服務。

Dreamweaver CS6
視覺化網頁開發工具