最近一段时间在学习angularjs
,因为以为直接使用它须要加载不少的js文件,所以想使用requirejs
来实现异步加载,并动态注入控制器。简单搜索了下发现好多教程写的都很复杂,因此打算写一下个人方法,算是学习笔记了。html
demo目录以下图:angularjs
index.html
文件的内容:bootstrap
<!-- index.html --> <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>demo</title> <!-- 引入requirejs,并在main.js中初始化 --> <script data-main="main.js" src="libs/require.js"> </script> </head> <body> <div ng-view></div> </body> </html>
在引入main.js
后,就须要在其中完成requirejs
的初始化:数组
// main.js 'use strict'; (function (win) { require.config({ baseUrl: './', // 依赖相对路径 paths: { 'angular': 'libs/angular.min', 'angular-route': 'libs/angular-route.min' }, // 引入没有使用requirejs模块写法的类库 shim: { 'angular': { exports: 'angular' }, 'angular-route': { // angular-route依赖angular deps: ['angular'], exports: 'ngRoute' } } }); // 自动导入router.js模块,因为后缀名能够省略,故写做'router', // 并将模块返回的结果赋予到router中。 require(['angular','router'], function(angular,router){ // 手动启动angularjs,特别说明此处的bootstrap不是那个ui框架, // 而是angularjs的一个手动启动框架的函数 angular.bootstrap(document, ['blogApp']); }); })(window);
main.js
中完成了各模块的初始化,而且引入了router.js
。
下面咱们在router.js
中配置路由:promise
// router.js define(['angular', 'require', 'angular-route'], function (angular, require) { var blogApp = angular.module('blogApp',['ngRoute']); blogApp.config(['$routeProvider','$controllerProvider', function($routeProvider,$controllerProvider) { $routeProvider .when('/', { templateUrl:'templates/list.html', controller: 'ListCtrl', resolve:{ delay : ctrlRegister('ListCtrl',['controllers/ListCtrl.js']) } }) .when('/data', { templateUrl:'templates/data.html', controller: 'DataCtrl', resolve:{ delay : ctrlRegister('DataCtrl',['controllers/DataCtrl.js']) } }) .otherwise({ redirectTo: '/' }); function ctrlRegister (ctrlName, ctrlModule) { return function ($q) { var defer = $q.defer(); require(ctrlModule, function (controller) { $controllerProvider.register(ctrlName, controller); defer.resolve(); }); return defer.promise; } } } ]); return blogApp; });
我把这里面拆为分三个部分来讲
第一部分:定义该模块框架
// 引入3个基础模块 define(['angular', 'require', 'angular-route'], function (angular, require) { // 定义整个demo为一个名为blogApp的模块 var blogApp = angular.module('blogApp',['ngRoute']); // ...第二部分:路由配置... // ...第三部分:复用的动态注入控制器函数 // 向main.js返回这个blogApp return blogApp; });
第二部分:设置基础路由异步
blogApp.config(['$routeProvider','$controllerProvider', function($routeProvider,$controllerProvider) { $routeProvider .when('/', { // 模板地址 templateUrl:'templates/list.html', // 控制器的名字 controller: 'ListCtrl', // resolve用来在完成路由前处理一些事 // 这里用来动态加载并注入相应的控制器 resolve:{ // ctrlRegister为我本身写的一个复用的函数, // 用于注入控制器。见第三部分 delay : ctrlRegister('ListCtrl',['controllers/ListCtrl.js']) } }); } }
第三部分:复用的控制器注入函数ide
// 该函数接受两个参数 // ctrlName,字符串类型,为该控制器的名字 // ctrlModule,字符串数组类型,为要引入的控制器的相对地址 // 调用例如 ctrlRegister('ListCtrl',['controllers/ListCtrl.js']) function ctrlRegister (ctrlName, ctrlModule) { return function ($q) { var defer = $q.defer(); // 加载该控制器,并将返回值赋给controller,返回值通常是一个控制器函数 require(ctrlModule, function (controller) { // 将返回值注册为名称为ctrlName的控制器 $controllerProvider.register(ctrlName, controller); defer.resolve(); }); // 完成注册 return defer.promise; } }
好了,这样就完成了动态加载的功能了,下面就能够写要动态加载的控制器了
用其中一个控制器ListCtrl.js
来讲明问题:函数
// ListCtrl.js // 加载angular模块 define(['angular'], function (angular) { 将本控制器函数做为结果返回给router.js return function ListCtrl( $scope ){ $scope.lists = ['1','2','3']; }; });
剩下的事情就是在list.html
中接收控制器传送的数据了:requirejs
<!-- list.html --> <ul> <li ng-repeat="list in lists"><a href="#/{{list}}" ng-bind="list"></a></li> </ul>
最终实现的功能是:
好比我访问http://127.0.0.1/demo/#/
只会加载list.html
和ListCtrl.js
;
而当访问http://127.0.0.1/demo/#/data
就只会加载data.html
和DataCtrl.js
。这样作有什么好处呢?当有不少控制器时,能够按需加载相应的控制器,不会一股脑所有加载上来(看起来依然并无什么卵用)。很惭愧,只为你们节约了一点微小的带宽,谢谢你们。