按需加载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 只在组 ...
随机推荐
- Flow-based model
文章1: NICE: NON-LINEAR INDEPENDENT COMPONENTS ESTIMATION 文章2:Real-valued Non-Volume Preserving (Real ...
- nginx搭建及加固
系统使用的是centos7 Nginx安装及配置 Nginx (engine x) 是一个高性能的HTTP和反向代理web服务器,同时也提供了IMAP/POP3/SMTP服务 安装 我是用的环境是ce ...
- [易学易懂系列|rustlang语言|零基础|快速入门|(17)|装箱crates]
[易学易懂系列|rustlang语言|零基础|快速入门|(17)|装箱crates] 实用知识 装箱crates 我们今天来讲讲装箱技术crates. 什么是crates? 英语翻译是: 英 [kre ...
- 使用Hbuilder打包app
使用Hbuilder来打包自己的H5项目 第一步 在Hbuilder上新建一个"移动APP"wolf(项目命名随意)(如果没用引用mui框架的东西,"选择模板" ...
- MySQL--关于MySQL练习过程中遇到的AVG()函数处理空值的问题
最近正准备面试,所以本来不怎么熟悉的SQL语句迫切需要练习,学习一下 在此感谢 笨鸟先飞-天道酬勤 大佬的博客:https://blog.csdn.net/dehu_zhou/article/deta ...
- 24. ClustrixDB 持久性配置文件
这些持久性选项不适用于内存中的表.有关更多信息,请参见内存表. ClustrixDB提供了一个选项,通过指定如何提交事务并使其持久,从而提高性能.当提交成功通知应用程序时,用户可以在提交过程中指定提交 ...
- CSS3 3D转换——rotateX(),rotateY(),rotateZ()
CSS3 允许使用 3D 转换来对元素进行格式化. ㈠浏览器支持 Internet Explorer 10 和 Firefox 支持 3D 转换. Chrome 和 Safari 需要前缀 -webk ...
- TensorFlow使用记录 (一): 基本概念
基本使用 使用graph来表示计算任务 在被称之为Session的上下文中执行graph 使用tensor表示数据 通过Variable维护状态 使用feed和fetch可以为任意的操作(op)赋值或 ...
- 利用jquery动态添加和删除表格的一行,并且保存单行数据
开发时遇到一个需求:要求要在页面的表格可以添加和删除一行,并能填写对应的数据后保存这一行数据. HTML代码 界面使用了freemarker框架,teams是后台传过来的list类型数据 <fo ...
- 超全详解Java开发环境搭建
摘自:https://www.cnblogs.com/wangjiming/p/11278577.html 超全详解Java开发环境搭建 在项目产品开发中,开发环境搭建是软件开发的首要阶段,也是必 ...