AngularJS + ui-router + RequireJS異步加載注冊controller/directive/filter/service
一般情況下我們會將項目所用到的controller/directive/filter/sercive預先加載完再初始化AngularJS模塊,但是當項目比較復雜的情況下,應該是打開對應的界面才加載對應的controller等資源,但是AngularJS一旦初始化,之后加載的controller/directive/filter/sercive是不會自動注冊到模塊上的。用AngularJS + ui-router + RequireJS來構建項目應該是比較常見的,所以我就基于這個條件來看看如何解決這個問題。
目錄結構:
HTML結構非常簡單,兩個鏈接,分別改變路由切換到不同子頁面:
<html>
<head>
<title>AngularJS + ui-router + RequireJS異步加載注冊controller</title>
</head>
<body>
<a href="#home">home</a>
<a href="#local">local</a>
<div ui-view></div>
<script type="text/javascript" src="js/require.js" data-main="js/main"></script>
</body>
</html>
main.js配置文件路徑,初始化模塊
require.config({
baseUrl: 'js',
paths: {
'app': 'app',
'angular': 'angular.min',
'router': 'angular-ui-router'
},
shim: {
'router': {
deps: ['angular']
}
}
})
// 手動初始化myModule模塊
require(['app'],function(){
angular.bootstrap(document, ['myModule'])
})
app.js配置路由并返回myModule模塊
define(['router'],function(){
var app = angular.module("myModule", ['ui.router'])
.config(function($stateProvider, $urlRouterProvider){
$urlRouterProvider.otherwise('home');
$stateProvider
.state("home",{
url:"/home",
template: '<p>這里是home頁面</p>'
})
.state("local",{
url:"/local",
template: '<p>這里是local頁面</p>'
})
})
return app;
})
界面如下,現在可以點擊home和local切換到對應的子頁面
接下來要做的是,切換到home界面要加載homeCtrl控制器,切換到local頁面加載localCtrl控制器,我們將會用到$controllerProvider來手動注冊控制器。怎么拿到$controllerProvider到引用呢?
對angular應用來說,模塊對象是全局的,正好可以用來保存$controllerProvider的引用
在app.js文件define內部加上以下代碼
app.config(function($controllerProvider,$compileProvider,$filterProvider,$provide){
app.register = {
//得到$controllerProvider的引用
controller : $controllerProvider.register,
//同樣的,這里也可以保存directive/filter/service的引用
directive: $compileProvider.directive,
filter: $compileProvider.register,
service: $provide.service
};
})
接著在路由中配置要加載的控制器/指令/過濾器/服務
.config(['$stateProvider','$urlRouterProvider',function($stateProvider, $urlRouterProvider){
$urlRouterProvider.otherwise('home');
$stateProvider
.state("home",{
url:"/home",
controller: 'homeCtrl',
template: '<p>{{str}}</p>',
resolve: {
loadCtrl: ["$q", function($q) {
var deferred = $q.defer();
//異步加載controller/directive/filter/service
require([
'controller/homeCtrl'
], function() { deferred.resolve(); });
return deferred.promise;
}]
}
})
.state("local",{
url:"/local",
controller: 'localCtrl',
template: '<p>{{str}}</p>',
resolve: {
loadCtrl: ["$q", function($q) {
var deferred = $q.defer();
//異步加載controller/directive/filter/service
require([
'controller/localCtrl'
], function() { deferred.resolve(); });
return deferred.promise;
}]
}
})
}])
最后是控制器的寫法,為了省事就兩個寫在一塊了
define(['app'],function(app){
app.register
.controller('homeCtrl', function($scope){
$scope.str = 'home page';
})
app.register
.controller('localCtrl',function($scope){
$scope.str = 'local page'
})
})
刷新頁面, 就可以動態加載controller了。
directive/filter/service的寫法類似于controller,不再贅述,自己動手豐衣足食。 實例放在git上
By:古德God于 2016/01/15 00:30:47
原文鏈接:http://www.cnblogs.com/wangmeijian/p/5020788.html