一、多视图应用

AngularJS 通过路由支持多视图应用, 可以根据路由动态加载所需的视图。随着视图的不断增加, js文件会越来越多, 而 AngularJS 默认需要把全部的 js 都一次性加载, 使用起来非常不便, 因此按需加载模块的需求会越来越强, 不过, AngularJS 并没有实现按需加载。

二、异步加载

关于异步加载, AngularJS 的开发指南中有这样一段话:

Modules are a way of managing $injector configuration, and have nothing to do with loading of scripts into a VM. There are existing projects which deal with script loading, which may be used with Angular. Because modules do nothing at load time they can be loaded into the VM in any order and thus script loaders can take advantage of this property and parallelize the loading process.

这段话的大意是说 AngularJS 的模块只关注依赖注入,不关注脚本是怎么加载的。 目前已经有项目来处理脚本加载, 可以和 AngularJS 一起使用。 模块在加载的过程中什么都没做, 可以按照任意顺序加载, 因此脚本加载器可以使用这个特性进行并发加载。

AngularJS 在 $routeProvider 的文档中, when 方法的 route 参数有这样一个属性:

  • resolve - {Object.<string, function>=} - An optional map of dependencies which should be injected into the controller. If any of these dependencies are promises, the router will wait for them all to be resolved or one to be rejected before the controller is instantiated.

route 的 resolve 参数是一个可选依赖的 map 对象, 如果这个对象有成员是 promise 对象, 路由就会等待 promise 对象完成再初始化 controller 。

可以通过这一点, 来刻意创建一个 promise 对象加载需要的模块, 比如下面的代码:

 $routeProvider.when('/myView', {
controller: 'MyController',
templateUrl: '/views/myView.html',
resolve: {
deps: function($q, $rootScope) {
var defered = $q.defer();
require(dependencies, function() {
$rootScope.$apply(function() {
defered.resolve();
});
});
return defered.promise;
}
}
});

为此, 可以单独写一个 loader.js 来生成 promise 对象, 代码如下:

 define([], function() {
return function(dependencies) {
// 返回路由的 resolve 定义,
var definition = {
// resolver 是一个函数, 返回一个 promise 对象;
resolver: ['$q', '$rootScope', function($q, $rootScope) {
// 创建一个延迟执行的 promise 对象
var defered = $q.defer();
// 使用 requirejs 的 require 方法加载的脚本
require(dependencies, function() {
$rootScope.$apply(function() {
// 加载完脚本之后, 完成 promise 对象;
defered.resolve();
});
});
// 返回延迟执行的 promise 对象, route 会等待 promise 对象完成
return defered.promise;
}]
};
return definition;
}
});

将应用的路由单独放在一个 route.js 文件中进行定义:

 define([], function () {
return {
defaultRoute: '/welcome',
routes: {
'/welcome': {
templateUrl: 'components/welcome/welcomeView.html',
controller: 'WelcomeController',
dependencies: ['components/welcome/welcomeController']
},
'/dialogs': {
templateUrl: 'components/dialogs/dialogsView.html',
controller: 'DialogsController',
dependencies: ['components/dialogs/dialogsController']
},
'/list': {
templateUrl: 'components/list/listView.html',
controller: 'ListController',
dependencies: ['components/list/listController']
},
'/user': {
templateUrl: 'components/user/userView.html',
controller: 'UserController',
dependencies: ['components/user/userController']
},
'/help': {
templateUrl: 'components/help/helpView.html',
controller: 'HelpController',
dependencies: ['components/help/helpController']
}
}
};
});

$routeProvider 根据上面的定义进行初始化:

 if (routeConfig.routes != undefined) {
angular.forEach(routeConfig.routes, function(route, path) {
$routeProvider.when(path, {
templateUrl: route.templateUrl,
controller: route.controller,
// 设置每个路由的 resolve , 使用 requirejs 加载 controller 脚本
resolve: loader(route.dependencies)
});
});
} if (routeConfig.defaultRoute != undefined) {
$routeProvider.otherwise({ redirectTo: routeConfig.defaultRoute });
}

三、手工注册 controller

对于动态加载下来的 controller 需要手工注册, 这就需要调用 $controllerProvider 的 register 方法, 为了方便使用, 可以定义一个全局的 app 对象, 将 AngularJS 的注册 controller 、 directive 、 filter 、 factory 、 service 方法都暴露出来, 代码如下:

 define(['app.routes', 'app.loader', 'angular', 'angular-route'], function (config, loader) {
'use strict'; var app = angular.module('app', ['ngRoute', 'ngResource', 'ui.bootstrap']);
app.config(configure); configure.$inject = ['$routeProvider', '$locationProvider', '$controllerProvider', '$compileProvider', '$filterProvider', '$provide']; return app; function configure($routeProvider, $locationProvider, $controllerProvider, $compileProvider, $filterProvider, $provide) {
app.registerController = $controllerProvider.register;
app.registerDirective = $compileProvider.directive;
app.registerFilter = $filterProvider.register;
app.registerFactory = $provide.factory;
app.registerService = $provide.service;
}
});

有了这个 app 之后, 要做动态加载的 controller 就可以这样写了:

 // 将 controller 定义为一个 AMD 模块, 依赖上面的 app
define(['app'], function(app) {
'use strict';
// 调用 app 暴露的 registerController 方法注册 controller
app.registerController('HelpController', HelpController);
// 定义 controller 的注入对象;
HelpController.$inject = ['$scope'];
// controller 具体实现
function HelpController($scope) {
$scope.greeting = 'Help Info';
}
});

最新文章

  1. K近邻分类法
  2. Web service standards: SOAP, REST, OData, and more
  3. storm的数据源编程单元Spout学习整理
  4. extension 的一个应用 - 优化图片的读取机制
  5. python logging TimedRotatingFileHandler 作用
  6. Oracle session连接数和inactive的问题记录
  7. NHibernate 存储过程使用
  8. ORACLE 解析xml字符串-转载的
  9. DOM4J案例详解(添加 ,查询 ,删除 ,保存)
  10. CSS Content 属性
  11. docker进阶-初探Docker-compose
  12. ANDROID 中设计模式的采用--创建型模式
  13. [原创]GDB调试指南-断点设置
  14. Codeforces Round 504
  15. tensorflow 的数据管理
  16. el取bean 对象属性规则
  17. POJ 3660 Cow Contest(Floyd求传递闭包(可达矩阵))
  18. Intellij IDEA连接Spark集群
  19. mongodb-分组分页
  20. DB2创建表、操作表等常用命令

热门文章

  1. Django学习系列14:第一个数据库迁移
  2. java 枚举的用法
  3. 前端面试题-CSS优先级
  4. JAVA》eclipse——(二)Tomcat
  5. k8s-for批量拉取国内镜像并做tag标签
  6. Log4net日志文件自动按月份存放和日志独占问题的解决
  7. Centos 下硬盘分区的最佳方案
  8. hdu 2553 八皇后问题 基础
  9. Jmeter -- 同步定时器
  10. [CSP-S模拟测试]:表格(动态开点二维线段树+离散化)