在决定使用angularJS开发项目时,考虑到多人协作,模块化,扩展等等因素,决定引入requirJS实现js文件的异步加载,解决模块之间的依赖关系。
参考了一些关于angularJS项目的前端架构,都觉得不甚理想,幸运的是最终看到一篇关于angularJS如何集成requireJS的文章:
原文地址:如何将angularJS项目与requireJS集成
一、项目组织目录:
css 文件夹
img 文件夹
js 文件夹
– appIndex 文件夹
— api文件夹
— controller 文件夹
—- ctlModule.js
—- mainController.js
—- homeController.js
— directives 文件夹
— services 文件夹
— app.js
— index_main.js
— router.js
– appLogin 文件夹
— …
— 与appIndex类似
— …
- lib 文件夹
– angular 文件夹
— angular.js
— angular-ui-router.js
— …
– bootstrap 文件夹
– jquery 文件夹
– require 文件夹
– php 文件夹
– template 文件夹
— common 文件夹
— tplIndex 文件夹
— tplLogin文件夹
404.html
favicon.ico
humans.txt
index.html
LICENSE.txt
login.html
server.js
二、组织目录说明
两个大的模块,一个appIndex,代表前台展示模块;一个appLogin,代表登录模块。appLogin与appIndex类似,以appIndex为例:
appIndex下的文件夹:
api: 与后端交互
controllers: 控制器
directives: 指令
services: 服务
appIndex下的文件:
app.js 定义整个项目的module
index_main.js 配置脚本文件,启动angular
router.js 定义路由
api下的文件:
apiModule.js 定义api的module
mainApi.js 加载所有的api文件
homeApi.js 一个普通的api文件
controllers下的文件:
ctlModule.js 定义控制器的module
mainController.js 加载所有的控制器文件
homeController.js 一个普通的控制器文件
directives下的文件:
dirModule.js 定义指令的module
mainDirective.js 加载所有的指令文件
headerDirective.js 一个普通的指令文件
services下的文件:
serModule.js 定义服务的module
mainService.js 加载所有的服务文件
homeService.js 一个普通的服务文件
三、命名约定
$stateProvider.state(‘home’,{
url: ‘/home’,
templateUrl:’../../template/tplIndex/home.html’,
controller:’homeCtl’
})
以homeController为例:
对应的模板为home.html
控制器名字:homeCtl
return ctl.controller(‘homeCtl’,function($scope,person,serGetTitle,testData){
…
});
})
homeCtl里使用的服务,看到ser开头的,如serGetTitle,对应到homeService.js里查找,看到Data结尾的,如testData,对应到homeApi.js里查找
四、代码分析
1、index.html 主要代码如下:
<!doctype html>
<div>
<ul>
<li><a href="#/home">home</a></li>
</ul>
</div>
<div ui-view></div>
<rabbit-footer></rabbit-footer>
</body>
在首页index.html只需要引入requireJs库文件,并且指明入口函数main.js,采用手动启动angularjs应用,所以这里不用为首页添加ng-app=’rabbit’。
2、index_main.js 主要代码如下:
require.config({
baseUrl:’js’,
paths:{
jquery:’../lib/jquery/jquery-1.9.1’,
angular:’../lib/angular/angular’,
angularUiRouter:’../lib/angular/angular-ui-router’,
Restangular:’../lib/angular/restangular-1.5.2’,
lodash:’../lib/angular/lodash-1.8.3’,
app:’appIndex/app’,
router:’appIndex/router’,
mainController:’appIndex/controllers/mainController’,
ctlModule:’appIndex/controllers/ctlModule’,
homeController:’appIndex/controllers/homeController’,
…
},
shim:{
‘angular’:{
exports:’angular’
},
‘angularUiRouter’:{
deps: [‘angular’],
exports:’angularUiRouter’
},
…
},
urlArgs:”bust=” + (new Date()).getTime() //防止读取缓存,调试用
});
require([
‘jquery’,
‘angular’,
‘angularUiRouter’,
‘app’,
‘router’
], function ($,angular,angularUiRouter,app,router) {
$(document).ready(function(){
//采用手动启动angularjs应用,所以这里不用为首页添加ng-app=’rabbit’
angular.bootstrap(document, [‘rabbit’]);
});
});
3、两个重要的文件app.js和router.js
app.js 主要代码如下:
define([“angular”,’mainController’,’mainDirective’,’mainService’,’mainApi’],function(angular){
return angular.module(“rabbit”,[‘ui.router’,’app.ctlModule’,’app.dirModule’,’app.serModule’,’app.apiModule’]);
})
定义匿名模块:依赖的mainController和mainDirective主要是用来加载angular的控制器和指令
ui.router:一个基于ngRoute开发的第三方路由,作为框架额外的附加功能,它们都将以模块依赖的形式被引入
rabbit为自定义的模块名,依赖第三方路由模块ui.router,以及自定义的控制器模块,自定义的指令模块
这样做的目的是:在程序启动(bootstrap)的时候,加载依赖模块(如:ui.router),将所有挂载在该模块的服务(provider),指令(directive),过滤器(filter)等都进行注册,那么在后面的程序中便可以调用了。
router.js 主要代码如下:
define([‘app’],function(app){
return app.run([‘$rootScope’, ‘$log’, function($rootScope, $log){
$rootScope.$on(‘$stateChangeSuccess’, function(event, toState, toParams, fromState, fromParams){
$log.debug(‘successfully changed states’) ;
});
}])
.config(function($stateProvider, $urlRouterProvider, $locationProvider, $uiViewScrollProvider){
// 默认进入重定向
//$urlRouterProvider.otherwise(‘/index’);
$stateProvider.state(‘home’,{
url: ‘/home’,
templateUrl:’../../template/tplIndex/home.html’,
controller:’homeCtl’
})
})
});
配置了一个指定 /home 的路由。
4、控制器
mainController.js 主要代码如下:
define([‘homeController’,’indexController’], function() {});
主要用来加载各个控制器(所有的控制器都将在这个文件中被加载),我们可以有很多个控制器文件,按照具体需要进行添加。
homeController.js 主要代码如下:
define([‘ctlModule’,’jquery’],function(ctl,$){
return ctl.controller(‘homeCtl’,function($scope,serGetTitle,testData){
$scope.title = serGetTitle.title;
$scope.projects = testData.getMessages();
})
})
控制器homeCtl依赖于ctlModule模块,其实可以理解为app.ctlModule模块下的一个“方法”。
ctlModule.js 主要代码如下:
define([‘angular’], function (angular) {
‘use strict’;
return angular.module(‘app.ctlModule’, []);
});
声明一个叫作app.ctlModule的模块,app.js里的模块rabbit,依赖于这个模块,并调用这个模块下的所有“方法”
5、指令,服务,接口
同控制器的定义方法完全类似。
五、说明
php文件夹放了一些php文件,可以用apache建一个站点,模拟与服务器端的数据交互。
server.js是一个静态文件服务器,mac下进入目录,执行node server,即可创建一个简单的nodejs服务器。
个人感觉这样设计一个前端架构,虽然会让开发变得繁琐,但功能划分比较明确,提供了一个开发标准,适合于多人协同作业,总体上来说利大于弊。
源码下载地址:angularJS集成requireJS