回顧
上一篇文章主要講解了創建兼容任意瀏覽器(主要是ie的一些奇葩問題)的angularjs web應用,但是項目開發中其實更重要的還是在功能的模塊化、代碼自動壓縮上面,這樣項目在后期維護或者功能的重復利用上才會更方便,那么今天主要圍繞以下幾個主題來講講如何在不是用其他js模塊化庫的情況下,開發便於管理的angualrjs模塊化代碼:
- 使用service來創建模塊
- 模塊間引用
- 代碼合並及壓縮
本文中的代碼均已nodejs來實現。
nodejs中,使用UglifyJS2來實現代碼壓縮
使用service來創建模塊
以前創建angualrjs應用都是直接基於對scope的直接綁定來完成的,例如:登錄功能,代碼如下:
//html
<div ng-controller="loginController">
<div>
用戶名:
<input type="text" ng-model="name" />
</div>
<div>
密 碼:
<input type="password" ng-model="pwd" />
</div>
<a href="javascript:void(0)" ng-click="login()">
登錄
</a>
</div>
//js
var myApp = angular.module('myApp', []);
myApp.controller('loginController', function ($scope) {
$scope.name = '';
$scope.pwd = '';
$scope.login = function () {
//代碼略
};
});
當有很多的功能的時候,有些人可能會創建很多的controller來完成,也有些人會像我一樣,使用一些js模塊化庫(seajs\requirejs)來實現,但是整合js模塊化庫會帶來一些問題,而且效果也不盡人意,代碼也會變得很復雜。
鑒於以上的一些問題,我不得不尋找一些其他的方案來替代,於是后來就想到了使用service來替代模塊化(可能是資質比較差的原因吧),這樣便可以充分利用angularjs的特性來完成,首先創建一個user的service,其實就是將當前scope內的代碼遷移到user.js內,代碼如下:
myApp.service('user', function () {
function User() {
this.name = '';
this.pwd = '';
}
User.prototype.login = function () {
//代碼略
};
return new User();
});
然后只要稍微修改一下上面的代碼便可以實現這個功能了,改完代碼如下:
//html
<div ng-controller="loginController">
<div>
用戶名:
<input type="text" ng-model="user.name" />
</div>
<div>
密 碼:
<input type="password" ng-model="user.pwd" />
</div>
<a href="javascript:void(0)" ng-click="user.login()">
登錄
</a>
</div>
//js
myApp.controller('loginController', function ($scope, user) {
$scope.user = user;
});
使用這種方法,功能開發就簡單多了,只要將功能的代碼變成一個個的js,然后頁面上引用后在controller初始化的時候,一個個綁定到scope上就可以了。
模塊間引用
項目開發當中,免不了模塊之間的交互,由於以上我們只用了service來創建模塊,而angularjs的service跟許多js模塊化庫是一樣的,不允許模塊之間的循環引用,這樣如果我們有一個user和userAddress,當user需要引用userAddress的時候就會遇到一些問題。
遇到此類問題的時候,其實可以引入一個類似緩存的模塊來解決,首先將所有的功能模塊都加入到緩存模塊中(controller內),然后當user模塊需要引用到userAddress模塊的時候,只要引用緩存模塊並從其開放的接口中獲取userAddress模塊即可。
其實緩存模塊就只要有2個方法(get\set),大致代碼如下:
myApp.controller('loginController', function ($scope, cache, user, userAddress) {
$scope.user = user;
$scope.userAddress = userAddress;
caceh.set('user', user);
caceh.set('userAddress', userAddress);
});
//user
myApp.service('user', function(cache) {
//需要引用的時候
var userAddress = cache.get('userAddress');
//其他代碼省略
});
代碼合並及壓縮
當功能模塊越來越多的時候,controller內就會有很多類似的代碼了,而且每增加一個js模塊,都需要在controller內注冊並添加到cache中去,實在是很麻煩。
其實大家應該已經發現了,只要我們將模塊放在同一的文件夾內,然后通過掃描這個文件夾,並使用模板來進行代碼生成就可以免去這些麻煩的注冊代碼了,代碼如下:
//模板
window.myApp= angular.module('myApp', []);
myApp.controller('mainController', function ($scope, cache, <%= modules.join(', ') %>){
<% modules.forEach(function (m){ %>
$scope.<%= m %> = <%= m %>;
cache.set('<%= m %>', <%= m %>);
<% }) %>
});
<% codes.forEach(function (c){ %>
<%- code %>
<% }) %>
//合並
var ejs = require('ejs');
var fs = require('fs');
var path = require('path');
var jsDir = 'js文件夾路徑';
var codes = [];
var modules = [];
fs.readdirSync(jsDir).forEach(function (filename) {
if (filename.indexOf('.js') == -1)
return;
codes.push(fs.readFileSync(path.join(jsDir, filename), 'utf8'));
modules.push(filename.replace('.js', ''));
});
var tplCode = fs.readFileSync('模板路徑', 'utf8');
codes.unshift(ejs.render(tplCode, {
modules: modules,
codes: codes
}));
fs.writeFileSync('整合后的js文件路徑', codes.join('\r\n'), 'utf8');
這樣我們便可以在js文件變化的時候,通過合並所有的js,但是這里要注意將功能模塊的js和公用庫的js放在不同的文件夾下,引用公用代碼並不會去引用功能模塊,因此不需要加入到cache中去,並在合並的時候通過額外的代碼去拼接公用js。
通過以上的操作,我們只需要在頁面上只引入一個js,這樣開發起來也會比較方便,但是測試的時候,就略微麻煩。
在這里我建議將angularjs創建module和controller的生成代碼獨立放在一個生成模塊中,並生成一個js(如:config);將合並公用js和模塊js放在另一個生成模塊中;並在項目中添加一個諸如development的變量來標識是否為開發模式。
開發模式的時候,頁面上引用生成的config及其他公用js和功能js;非開發者模式下,則引用合並且壓縮后的js,示例代碼如下:
<%
var app = process.app;
if (app.get('development')) {
%>
<script type="text/javascript" src="/js/config.js"></script>
<script type="text/javascript" src="/js/lib/cache.js"></script>
<script type="text/javascript" src="/js/main/user.js"></script>
<script type="text/javascript" src="/js/main/userAddress.js"></script>
<% }
else { %>
<script type="text/javascript" src="/js/myApp.min.js"></script>
<% } %>
2個代碼生成的模塊代碼這里就不再寫出來了,因此大致的代碼上面都已經給出來了,其他的就靠大家自己根據實際情況去重構了,^_^。
壓縮js腳本的代碼也不寫了,具體的可以查看文章開頭的UglifyJS2的示例代碼,需要注意的是except參數是不能少的,不然會將合並腳本內的angularjs的模塊名和功能模塊名替換成其他的簡單變量,項目運行起來會出現錯誤。
結尾
由於近段時間都是使用angualrjs配合nodejs來進行開發的,開發中遇到的問題和解決的方案整理了一下跟大家分享一下,希望對大家有所幫助。
大致的代碼基本上都有提供,其他的就要靠大家自己去編碼了,這樣才能將分享的東西轉化成自己的。
今天的文章就到這里了,如果有什么錯誤、問題請留言給我,謝謝大家!
