angularJS+ui-router+requireJS非同步載入controller、directive、filter
阿新 • • 發佈:2018-12-30
開發比較複雜的單頁面應用時,往往包括比較多的控制器、服務等,如果這些js檔案都在頁面開啟時就全部載入,往往載入量大,耗時長;因此,當開啟對應的頁面才載入響應的控制器等資源時,能一定程度地優化頁面載入速度。
· 專案目錄結構:
· index.html:
<html>
<head>
<title></title>
</head>
<body>
<div ui-view></div>
<script type="text/javascript" src="js/libs/require.js" data-main="js/main"></script>
</body>
</html>
· main.js
require.config({
baseUrl: 'js',
paths: {
'app': 'app',
'angular': 'libs/angular.min',
'router': 'libs/angular-ui-router'
},
shim: {
'angular': {
exports: 'angular'
},
'router': {
deps: ['angular']
},
'app': {
deps: ['router']
}
}
})
// 手動初始化myModule模組
require(['app'],function(){
angular.bootstrap(document, ['myModule'])
})
在main.js中配置檔案路徑,初始化模組。此處使用angular.bootstrap完成模組的手動載入。
· 各模組檢視
先來看一下views中包含的檔案:
home資料夾裡的是每一個檢視都包含的相同的檢視部分,比如PC網站每一個頁面都有相同的導航欄,底部版權資訊,這類檢視分塊就可以單獨抽出來,再在app.js中巢狀到路由中。
../home/index.html:
<!--主模組結構-->
<div class="container">
<div ui-view="topbar"></div>
<div ui-view="main"></div>
<div ui-view="footer"></div>
</div>
../home/topbar.html:
<a ui-sref="index">首頁</a>
<a ui-sref="index.news">資訊動態</a>
<a ui-sref="index.community">社群科普</a>
<a ui-sref="index.resource">科普資源</a>
<a ui-sref="index.signin">活動報名</a>
<a ui-sref="index.learn">線上學習</a>
<a ui-sref="index.notice">通知公告</a>
<a ui-sref="index.service">志願者服務</a>
<a ui-sref="index.about">關於我們</a>
· app.js
define(['angular','router'],function(){
var app = angular.module("myModule", ['ui.router'])
app.config(function($controllerProvider,$compileProvider,$filterProvider,$provide){
app.register = {
//得到$controllerProvider的引用
controller : $controllerProvider.register,
//同樣的,這裡也可以儲存directive/filter/service的引用
directive: $compileProvider.directive,
filter: $filterProvider.register,
service: $provide.service
};
})
.config(['$stateProvider','$urlRouterProvider',function($stateProvider, $urlRouterProvider){
$urlRouterProvider.otherwise('/index');
$stateProvider
.state("index",{
url:"/index",
views: {
'': {
templateUrl: 'views/home/index.html'
},
'[email protected]': {
templateUrl: 'views/home/topbar.html'
},
'[email protected]': {
templateUrl: 'views/home/home.html'
},
'[email protected]': {
templateUrl: 'views/home/footer.html'
}
}
})
// 模組1
.state("index.news",{
url:"/news",
views: {
'[email protected]': {
templateUrl: 'views/modules/news/news.html',
controller: 'newsCtrl',
resolve: {
loadCtrl: ["$q", function($q) {
var deferred = $q.defer();
//非同步載入controller/directive/filter/service
require([
'directives/myDirective',
'filters/sexFilter',
'controller/newsCtrl'
], function() { deferred.resolve(); });
return deferred.promise;
}]
},
}
}
})
// 模組2
.state("index.about",{
url:"/about",
views: {
'[email protected]': {
templateUrl: 'views/modules/about/about.html',
controller: 'aboutCtrl',
resolve: {
loadCtrl: ["$q", function($q) {
var deferred = $q.defer();
//非同步載入controller/directive/filter/service
require([
'controller/aboutCtrl'
], function() { deferred.resolve(); });
return deferred.promise;
}]
}
}
},
})
}])
return app;
})
此處使用了路由巢狀,由於views可能包含多個檢視,所以對應檢視的controller記得寫在響應的檢視定義區域內噢。
· newsService.js:
define(['app'],function(app){
//Service比較特殊,載入後還需要手動注入控制器
app.register.service('newsService', function($http, $q){
return {
getData:function(){
var deferred = $q.defer();
var promise = $http.get("/json/news.json");
promise.then(
// 通訊成功的處理
function(answer){
//在這裡可以對返回的資料集做一定的處理,再交由controller進行處理
answer.status = true;
deferred.resolve(answer);
},
// 通訊失敗的處理
function(error){
// 可以先對失敗的資料集做處理,再交由controller進行處理
error.status = false;
deferred.reject(error);
console.log("獲取資訊動態資料失敗");
});
//返回promise物件,交由controller繼續處理成功、失敗的業務回撥
return deferred.promise;
}
}
})
})
· newsCtrl.js:
define(['app','service/newsService'],function(app){
// 控制器 將伺服器手動注入控制器中
app.register.controller('newsCtrl', function($scope,newsService){
newsService.getData().then(
function(answer){
$scope.newsList = answer.data;
},
function(error){
$scope.error = error;
}
);
});
});
自定義指令以及過濾器的寫法也類似噢~