一、多视图应用

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';
}
});

按需加载controller——angular的更多相关文章

  1. Angular (SPA) WebPack模块化打包、按需加载解决方案完整实现

    文艺小说-?2F,言情小说-?3F,武侠小说-?9F long long ago time-1-1:A 使用工具,long long A ago time-1-2:A 使用分类工具,long long ...

  2. angularJS+requireJS实现controller及directive的按需加载

    最近因为项目的比较大,需要加载的js文件较多,为了提高首屏页面的加载速度,需要对js文件进行按需加载,然后网上参考了一些资料,自己也深入研究一番之后,实现了按需加载控制器js文件及指令js文件的效果: ...

  3. 原创《分享(Angular 和 Vue)按需加载的项目实践优化方案》

    针对前端优化的点有很多,例如:图片压缩,雪碧图,js/css/html 文件的压缩合并,  cdn缓存, 减少重定向, 按需加载 等等 最近有心想针对 ionic项目 和 vue项目,做一个比较大的优 ...

  4. angular中按需加载js

    按需加载估计是大家在使用angular之后最想解决的问题吧,因为angular的依赖机制,导致了必须在第一次加载的时候就加载所有js文件,小项目还好,稍大一点的项目如果有上百个js文件,不管是从效率还 ...

  5. angularJS 按需加载

    之前做应用的时候都会在首页就把全站的js预先加载进来... 怎么实现按需加载? 首先在$routeProvider里面加resolve属性,angular-route提供的resolve功能,也就是路 ...

  6. requirejs按需加载angularjs文件

    之前分享了一篇用ocLazyLoad实现按需加载angular js文件的博客.本来当时想会使用一种方法就行了.可最近刚好有时间,在网上查找了一下requirejs实现angular js文件按需加载 ...

  7. angularjs ocLazyLoad分步加载js文件,angularjs ocLazyLoad按需加载js

    用angular有一段时间了,平日里只顾着写代码,没有注意到性能优化的问题,而今有时间,于是捋了捋,讲学习过程记录于此: 问题描述:由于采用angular做了网页的单页面应用,需要一次性在主布局中将所 ...

  8. AngularJS中的按需加载ocLazyLoad

    欢迎大家讨论与指导 : ) 初学者,有不足的地方希望各位指出 一.前言 ocLoayLoad是AngularJS的模块按需加载器.一般在小型项目里,首次加载页面就下载好所有的资源没有什么大问题.但是当 ...

  9. Vue按需加载提升用户体验

    Vue官方文档异步组件: 在大型应用中,我们可能需要将应用拆分为多个小模块,按需从服务器下载.为了让事情更简单, Vue.js 允许将组件定义为一个工厂函数,动态地解析组件的定义.Vue.js 只在组 ...

随机推荐

  1. 孕期出血是否先兆流产——B超看婴儿是否在子宫内+hcg值是否过低孕激素不足

    转自:http://blog.sina.com.cn/s/blog_4a869c130102e7nu.html 很多人都经历过孕早期阴道出血,但结局大不一样. 人类受孕后,从一个单细胞逐渐发育成为一个 ...

  2. kotlin面向对象之接口、代理与委托、单例模式

    接口: 对于什么是接口这里就不概述了,跟java中的概念一样,下面直接上代码进行操练: 而男人跟女人的接口当然也是不同的,很显然男人跟女人最大的差别就是拥有"小弟弟"[我黄我暴利] ...

  3. 关于LRU算法(转载)

      原文地址: http://flychao88.iteye.com/blog/1977653 http://blog.csdn.net/cjfeii/article/details/47259519 ...

  4. eclipse编码格式(中文乱码)

    https://jingyan.baidu.com/article/2009576193ee38cb0721b416.html 修改工作空间默认编码 1 进入Eclipse,导入一个项目工程,如果项目 ...

  5. .net post 字符串含有+号的时候,加号会变成空格 处理方法

    value= value.Replace("+", "%2B");  替换加号

  6. windows10禁止系统更新

  7. LA 3263 好看的一笔画 欧拉几何+计算几何模板

    题意:训练指南260 #include <cstdio> #include <cstring> #include <algorithm> #include < ...

  8. UVA 11178 Morley's Theorem 计算几何模板

    题意:训练指南259页 #include <iostream> #include <cstdio> #include <cstring> #include < ...

  9. 分享几个免费IP地址查询接口(API)

    淘宝IP地址库 提供的服务包括:1. 根据用户提供的IP地址,快速查询出该IP地址所在的地理信息和地理相关的信息,包括国家.省.市和运营商.2. 用户可以根据自己所在的位置和使用的IP地址更新我们的服 ...

  10. A. Detective Book

    A. Detective Book time limit per test 2 seconds memory limit per test 256 megabytes input standard i ...