另類angularjs應用


回顧

  上一篇文章主要講解了創建兼容任意瀏覽器(主要是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來進行開發的,開發中遇到的問題和解決的方案整理了一下跟大家分享一下,希望對大家有所幫助。

  大致的代碼基本上都有提供,其他的就要靠大家自己去編碼了,這樣才能將分享的東西轉化成自己的。

  今天的文章就到這里了,如果有什么錯誤、問題請留言給我,謝謝大家!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM