什么是UI-Router?
AngularJS 是一種富客戶端單頁(yè)面應(yīng)用框架,所以要在一個(gè)頁(yè)面呈現(xiàn)不同的視圖,路由起到了至關(guān)重要的作用。 UI-Router是Angular-UI提供的客戶端路由框架,它解決了原生的ng-route的不足(視圖不能嵌套,同一URL下不支持多個(gè)視圖)。例如實(shí)際的單頁(yè)面應(yīng)用中,導(dǎo)航欄用一個(gè)視圖,內(nèi)容部分用另一個(gè)視圖,就是比較常見(jiàn)的。
UI-Router提出了$state的概念。一個(gè)$state是一個(gè)當(dāng)前導(dǎo)航和UI的狀態(tài),每個(gè)$state需要綁定一個(gè)URL Pattern。 在控制器和模板中,通過(guò)改變$state來(lái)進(jìn)行URL的跳轉(zhuǎn)和路由。
如何使用UI-Router
UI-Router模塊是一個(gè)可選的angularJS模塊,如果需要使用,我們要單獨(dú)引用js。具體應(yīng)用示例如下:
<html>
<head>
<script src="lib/angular.js"></script>
<script src="lib/angular-ui-router.js"></script>
<script src="helloworld.js"></script>
<style>.active { color: red; font-weight: bold; }</style>
</head>
<body ng-app="helloworld">
<a ui-sref="hello" ui-sref-active="active">Hello</a>
<a ui-sref="about" ui-sref-active="active">About</a>
<ui-view></ui-view>
</body>
</html>
var myApp = angular.module('helloworld', ['ui.router']);
myApp.config(function($stateProvider) {
var helloState = {
name: 'hello',
url: '/hello',
template: '<h3>hello world!</h3>'
}
var aboutState = {
name: 'about',
url: '/about',
template: '<h3>Its the UI-Router hello world app!</h3>'
}
$stateProvider.state(helloState);
$stateProvider.state(aboutState);
});
路由加載的三種方法
//1、·調(diào)用$state.go方法
$state.go('detail', {id: 1});
$state.go(“index');
//2、點(diǎn)擊包含ui-sref指令的鏈接
<a ui-sref="contacts">Contacts</a>
<a ui-sref="contacts.detail({contactId: 42})">Contact 42</a>
//3、url跳轉(zhuǎn)
<a href="#/index" >index</a>
視圖嵌套
ui-router的視圖可以嵌套,視圖嵌套通常對(duì)應(yīng)著$state的嵌套。 index.detail是index的子$state,index_detail.html也將作為index.html的子頁(yè)面。ui-view可以配合$state進(jìn)行任意層級(jí)的嵌套, 即index_detail.html中仍然可以包含一個(gè)ui-view,它的$state可能是index.detail.hobbies。
視圖命名
在ui-router中,一個(gè)$state下可以有多個(gè)視圖,它們有各自的模板和控制器。如上面的示例代碼,hello和about就是兩個(gè)獨(dú)立的視圖,有各自的末班和控制器。
參數(shù)說(shuō)明:
- url:默認(rèn)相對(duì)路徑(以^開(kāi)頭的是絕對(duì)路徑)
- views:每個(gè)子視圖可以包含自己的模板、控制器和預(yù)載入數(shù)據(jù)。 (后2項(xiàng)選填,控制器可以在view中綁定)
- abstract:抽象模板不能被激活
- template: HTML字符串或者返回HTML字符串的函數(shù)
- templateUrl: HTML模板的路徑或者返回HTML模板路徑的函數(shù)
- templateProvider:返回HTML字符串的函數(shù)
- controller、controllerProvider:指定任何已經(jīng)被注冊(cè)的控制器或者一個(gè)作為控制器的函數(shù)
- resolve:在路由到達(dá)前預(yù)載入一系列依賴或者數(shù)據(jù),然后注入到控制器中。
- data:數(shù)據(jù)不會(huì)被注入到控制器中,用途是從父狀態(tài)傳遞數(shù)據(jù)到子狀態(tài)。
- onEnter/onExit:進(jìn)入或者離開(kāi)當(dāng)前狀態(tài)的視圖時(shí)會(huì)調(diào)用這兩個(gè)函數(shù).
- resolve 為控制器提供可選的依賴注入項(xiàng)。是由 key/value 組成的鍵值對(duì)象。
key – {string}:注入控制器的依賴項(xiàng)名稱。
value - {string|function}:
string:一個(gè)服務(wù)的別名
function:函數(shù)的返回值將作為依賴注入項(xiàng),如果函數(shù)是一個(gè)耗時(shí)的操作,那么控制器必須等待該函數(shù)執(zhí)行完成(be resolved)才會(huì)被實(shí)例化。
比如,視圖都需要用戶登錄后才能訪問(wèn),那么判斷是否登錄就可以做成一個(gè)控制器依賴
resolve: {authentication:['topicAuth', '$q', function(topicAuth, $q){ return $q.when().then(function(){ return topicAuth.authentication(); }); }]}
動(dòng)態(tài)加載模板/內(nèi)容
在實(shí)際使用時(shí)往往需要根據(jù)參數(shù)動(dòng)態(tài)加載不同模板/內(nèi)容。此時(shí)可以通過(guò)如下兩種方式實(shí)現(xiàn)。
//1、用參數(shù)作為文件名,拼接文件名加載
templateUrl: function ($stateParams){
return '/topic/detail_' + $stateParams.type + '.html';
}
//2、用參數(shù)賦值,修改內(nèi)容
templateProvider: function ($timeout, $stateParams) {
return $timeout(function () {
return '<h1>' + $stateParams.topicId + '</h1>'
}, 100);
}
路由參數(shù):
ui-router同樣支持切換視圖時(shí)傳遞參數(shù)。默認(rèn)有如下兩種方式傳遞參數(shù):
- 通過(guò)$stateParams傳遞。傳遞的參數(shù)是一個(gè)object。傳遞的方法有:
- ui-sref="index.detail({id:22})“
- $state.go('index.detail', {id: 22});
- 通過(guò)$location來(lái)獲取和設(shè)置URL。直接在controller里引入$stateParams 和$location即可。
state 為view controller提供自定義數(shù)據(jù)。
$stateProvider.state(‘blog.index', {
templateUrl: ’templates/blog_index.html',
data: {
currentPage: 1,
pageSize: 20
}
})
上面 data 對(duì)象就是自定義數(shù)據(jù),里面定義了頁(yè)面的當(dāng)前頁(yè)和顯示內(nèi)容條數(shù)。在視圖對(duì)應(yīng)的 controller 中我們就可以通過(guò)下面的方法來(lái)獲取自定義數(shù)據(jù).
console.log($state.current.data.currentPage); // 1
console.log($state.current.data.pageSize); // 20
如何判斷選中視圖選中
- $state.includes
返回 true / false,查看當(dāng)前狀態(tài)是否在某父狀態(tài)內(nèi),比如 $state.includes('contacts')<!-- 包含在 /contacts 狀態(tài)內(nèi)部,即其作為 parant state --> <li ng-class="{active: $state.includes('contacts')}"> <a ui-serif="contacts.list">Contacts</a> </li> - ui-sref-active
查看當(dāng)前激活狀態(tài)并設(shè)置 Class。例如<li ui-sref-active="active"><a ui-sref="about">About</a></li>
控制器引入的集中方法
$stateProvider.state('contacts', {//直接定義
template:'<h1>test</h1>',
controller: function($scope){
$scope.title = 'My Contacts';
}
}).state('contacts1', {//直接名稱引用
template:'<h1>test</h1>',
controller: 'ContactsCtrl'
}).state('contacts2', {//直接定義并且定義別名
template:'<h1>test</h1>',
controller: function(){
this.title = 'My Contacts';
},
controllerAs: 'contact'
}).state('contacts3', { //控制器名稱并且定義別名
template:'<h1>test</h1>',
controller: 'ContactsCtrl as contact'
}).state('contacts4', { //根據(jù)state動(dòng)態(tài)加載
template:'<h1>test</h1>',
controllerProvider: function($stateParams) {
var ctrlName = $stateParams.type + "Controller";
return ctrlName;
}
});
注意:如果未定義template,controller將不會(huì)被實(shí)例化
更多說(shuō)明:參考 https://github.com/angular-ui/ui-router/wiki