1、背景说明
最近一段时间,一直在研究angularjs及AMD、common规范等。但怎么把angularjs有效的与AMD模块组织结合在一起使用,还是值得深思。
本人研究一段时间,为了巩固下研究成果,特意写了一个demo,仅供参考。
2、使用技术点说明
kendo:主要使用kendo开源一些组件(由于本人对kendo研究比较多)
angular:angular作为基础框架(MVC、DI、数据绑定、页面路由、相关服务等)
requireJS:AMD模块加载器
bootstrap:主要使用它提供的一些样式
3、应用APP创建流程
app启动流程如下,
3.1 bootstrap
使用angular手动初始化启动angular应用程序,等待页面所有脚本加载完成后,找到html指定节点(默认是根节点),调用api/angular.bootstrap将模板编译成可执行的、数据双向绑定的应用程序
代码如下,
angular.element(document).ready(function(){ angular.bootstrap(angular.element("#incidentTest"), ['incident.app.module']); });
3.2 AMD模块依赖实现方式
使用AMD规范实现模块之间的依赖(加载器使用requirejs)。
这里需要啰嗦二句,有些第三方js库不符合AMD规范,如angularjs,所幸的是requirejs.config中有shim属性,支持非AMD模块加载
配置代码如下,
require.config({ //baseUrl: '', paths: { 'angular': "../../../node_modules/angular/angular", 'kendo': "../../../node_modules/kendo/LICENSE-2.0/kendo.ui.core.min", 'jquery': "../../../node_modules/jquery/jquery-1.9.1.min" shim: { 'angular': { deps: ['jquery'], exports: "angular" }, 'kendo': { deps: ['jquery', 'angular'] } } });
AMD模块定义如下,
define(['incidentappeal.module'],function(incidentappealModule){ })
3.3 angular模块依赖实现方式
使用angularjs提供的依赖注入机制,管理所有模块依赖
代码如下,
//create ui.module angular.module("ui.module", [ "ui.grid", 'ui.grid.pinning', 'ui.grid.resizeColumns', 'ui.grid.saveState', 'kendo.directives' ]);
3.4 模块加载方式
使用requirejs框架实现对AMD及非AMD模块载入
代码如下,
requireIncidentApp(["module.management"], function () { //go to app requireIncidentApp(['angular', 'incident.app.module'], function (angular) { //... }); }) })
3.5 angular Module中的controller、指令、服务、过滤器实现
使用angular提供的对应的provider。注入到angular框架体系,根据ui-router提供的resolve属性(如果有不明白resolve这个属性的同学,可以自己去查查)实现按需加载功能。
每个angular模块提供可拓展的register属性(里面包括controller、directive、filter、factory、service),代码如下,
workspaceModule.register={
controller:$controllerProvider.register,
directive:$compileProvider.directive,
filter:$filterProvider.register,
factory:$provide.factory,
service:$provide.service
};
在每个单独的controller、directive、filter、factory、service中实现自己的注册。代码如下,
workspaceModule.register.controller("workspace",myController);
})
3.6 国际化实现方式
使用npm 安装angular-translate
angularjs 国际化模块提供国际化服务,其他模块首先要依赖国际化模块,配置当前模块字条文件(.json),实现对当前模块的国际化。代码如下,
angular.module("incidentcommon.localization.module", [ "pascalprecht.translate", 'incidentcommon.routeconfig.module' ]);
var incidentCommonLocalizationModule = angular.module('incidentcommon.localization.module'); incidentCommonLocalizationModule.config([ '$translateProvider', 'constantRouteConfig' ,function ( $translateProvider, constantRouteConfig ){ $translateProvider.useStaticFilesLoader({ files:[{ prefix:constantRouteConfig['translate'].prefix, suffix:constantRouteConfig['translate'].suffix }] }); $translateProvider.preferredLanguage(constantRouteConfig['translate'].preferredLanguage); }]); incidentCommonLocalizationModule.factory('T', ['$translate', function ($translate) { var Trans = function (key) { if (key) { return $translate.instant(key); } return key; }; return Trans; }]); return incidentCommonLocalizationModule;
4、UI
4.1 单页面应用(ui-router、state)
单页面主要使用angular-ui-router技术,在workspace.module中实现。
ui-router中resolve属性,在view加载之前,angular会先把resolve作为view的一个依赖,按需加载配置的每个AMD模块,这样,根据用户浏览view的动作按需载入每个view所需要的依赖,如controller、
directive、factory等,代码如下,
workspace.left":route.resolve('workspace.left'); routeConfigs["workspace.left"] ={}; routeConfigs["workspace.left"].controllerDeps =""; routeConfigs["workspace.left"].controller=["workspace/workspace.content.controller"]; routeConfigs["workspace.left"].url ="workspace/workspace.content.html";
4.2 界面库使用及引入方式
界面库主要使用kendoui,使用kendo开源控件kendo.ui.core.js。另外加入一些kendo需要收费的控件,如angular-ui(ui-grid/ui-chart/ui-treeview)
引入方式,代码如下,
angular.module("ui.module", [ "ui.grid", 'ui.grid.pinning', 'ui.grid.resizeColumns', 'ui.grid.saveState', 'kendo.directives' ]);
4.3 样式控制
css样式直接在html引入,
<!--CSS -->
<link href="../../styles/bootstrap/bootstrap.min.css" rel="stylesheet" />
...
<link href="../../styles/styles.css" rel="stylesheet" />
4.4 表单验证
html5/angular/kendo自带的验证方式
5、代码框架结构图
代码框架结构图如下(这里只是一个简单示意图),
6、几个关键点说明
6.1 module.management集中式模块管理的引入
(1)、为了减少后面模块之间因AMD模块加载顺序导致模块间依赖出现不必要问题(如循环依赖,当然循环依赖还有其它解决方案)
(2)、减少AMD模块数量
(3)、将angualr模块创建及依赖配置放在一个AMD模块中进行管理,更加清晰。
6.2 以view为驱动实现按需加载
(1)、符合传统web多页面开发思想,每个view管理自己所依赖的js模块
(2)、angular-ui-router提供一套完善的注入机制,支持动态加载
(3)、后面的页面代码都是依赖view的业务去拓展,这些AMD模块会越来越多。但进入系统后,有些不常用的view一般不操作,导致有些模块的js或许永远都不会被使用,
这样不需要一次性把所有js文件下载到客户端。
7、缺陷
1、对打包支持不好。
另外,欢迎各位提出宝贵意见!
...待续,后面还会介绍一个angular+commonjs规范的demo,依赖webpack打包后才能运行