按需加载controller——angular
一、多视图应用
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的更多相关文章
- Angular (SPA) WebPack模块化打包、按需加载解决方案完整实现
文艺小说-?2F,言情小说-?3F,武侠小说-?9F long long ago time-1-1:A 使用工具,long long A ago time-1-2:A 使用分类工具,long long ...
- angularJS+requireJS实现controller及directive的按需加载
最近因为项目的比较大,需要加载的js文件较多,为了提高首屏页面的加载速度,需要对js文件进行按需加载,然后网上参考了一些资料,自己也深入研究一番之后,实现了按需加载控制器js文件及指令js文件的效果: ...
- 原创《分享(Angular 和 Vue)按需加载的项目实践优化方案》
针对前端优化的点有很多,例如:图片压缩,雪碧图,js/css/html 文件的压缩合并, cdn缓存, 减少重定向, 按需加载 等等 最近有心想针对 ionic项目 和 vue项目,做一个比较大的优 ...
- angular中按需加载js
按需加载估计是大家在使用angular之后最想解决的问题吧,因为angular的依赖机制,导致了必须在第一次加载的时候就加载所有js文件,小项目还好,稍大一点的项目如果有上百个js文件,不管是从效率还 ...
- angularJS 按需加载
之前做应用的时候都会在首页就把全站的js预先加载进来... 怎么实现按需加载? 首先在$routeProvider里面加resolve属性,angular-route提供的resolve功能,也就是路 ...
- requirejs按需加载angularjs文件
之前分享了一篇用ocLazyLoad实现按需加载angular js文件的博客.本来当时想会使用一种方法就行了.可最近刚好有时间,在网上查找了一下requirejs实现angular js文件按需加载 ...
- angularjs ocLazyLoad分步加载js文件,angularjs ocLazyLoad按需加载js
用angular有一段时间了,平日里只顾着写代码,没有注意到性能优化的问题,而今有时间,于是捋了捋,讲学习过程记录于此: 问题描述:由于采用angular做了网页的单页面应用,需要一次性在主布局中将所 ...
- AngularJS中的按需加载ocLazyLoad
欢迎大家讨论与指导 : ) 初学者,有不足的地方希望各位指出 一.前言 ocLoayLoad是AngularJS的模块按需加载器.一般在小型项目里,首次加载页面就下载好所有的资源没有什么大问题.但是当 ...
- Vue按需加载提升用户体验
Vue官方文档异步组件: 在大型应用中,我们可能需要将应用拆分为多个小模块,按需从服务器下载.为了让事情更简单, Vue.js 允许将组件定义为一个工厂函数,动态地解析组件的定义.Vue.js 只在组 ...
随机推荐
- 读《JavaScript面向对象编程指南》(一)
第二章 基础 通常认为在JavaScript中主要包括五种基本数据类型:数字.字符串.布尔值.undefined.null.任何不属于上述五种基本类型的值都被认为是一个对象. null和undefin ...
- 504错误解决办法 让你的浏览器强制在后端服务器执行而不用通过前端CDN服务器
因为后端执行时间过长,前端不等待,导致提示504错误的解决办法 504 错误是因为你的CDN服务器设置的延时有限, 超时导致的504 是前端不等待中止,是前端不行,后端应该正常 502 错误是后端 ...
- Python 实用爬虫-04-使用 BeautifulSoup 去水印下载 CSDN 博客图片
Python 实用爬虫-04-使用 BeautifulSoup 去水印下载 CSDN 博客图片 其实没太大用,就是方便一些,因为现在各个平台之间的图片都不能共享,比如说在 CSDN 不能用简书的图片, ...
- 添加了两个IP
//第一步:添加了两个IP root@default:~# ifconfig eth1:0 192.168.99.10 netmask 255.255.255.0 up root@default:~# ...
- solaris启动脚本S33installramdisk
脚本内容: state="$1" case "$state" in 'start') echo 'Starting install mr ramdisk' &g ...
- js 点击不同li 切换颜色
html <div> <li " onclick='addColor(this.id)'> 会议简介 </li> <li " onclic ...
- Gym - 102082G What Goes Up Must Come Down (树状数组+贪心)
题意:有一个长度为n的序列,你每次可以选择两个相邻的元素交换,求把这个序列排成单峰序列的最少交换次数. 方法一:将元素按数值从大到小排序(保存原来的位置),把最大的插在中间,剩下的依次往两边放,依次考 ...
- 基于django中settings中间件源码思想,实现功能的插拔式设计
这里我们用到一个非常重要的模块,importlib,利用它可以实现字符串转python代码,再利用反射进行操作,这样就可以实现插拔式设计. 一.我们先做个初级的,把所有文件放到初级思想文件夹下: 1. ...
- 2019春Python程序设计练习4(4.9-4.15)
1-1 如下代码可以实现当输入6的时候输出x>5,输入4的时候输出 3<x<=5,输入1的时候输出x<=3 x = int(input()) if x>5: print( ...
- 随机验证码生成和join 字符串
函数:string.join() Python中有join()和os.path.join()两个函数,具体作用如下: join(): 连接字符串数组.将字符串.元组.列表中的元素以指定的字符(分隔符) ...