最近一段時間在學習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
。這樣作有什麼好處呢?當有不少控制器時,能夠按需加載相應的控制器,不會一股腦所有加載上來(看起來依然並無什麼卵用)。很慚愧,只爲你們節約了一點微小的帶寬,謝謝你們。