回顾
上一篇文章主要讲解了创建兼容任意浏览器(主要是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 equirejs)来实现,但是整合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个方法(getset),大致代码如下:
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,