最近正在開發的項目以AngularJS開發,目前開發已經告一段落,打算近期整理一下開發階段中遇到的問題和個人感受。開發過程中接觸了一些AngularJS的常用庫,UI-ROUTER就是其中比較重要的路由庫,就從這裏開始寫起來。
UI-ROUTER官網上提供了3個簡單的教程,本篇就以這3個教程結合開發中的實際使用進行總結。
首先是熟悉的Hello World
。
<body ng-app='myApp'>
<ul>
<li><a ui-sref="hello" ui-sref-active="active">hello</a></li>
<li><a ui-sref="about" ui-sref-active="active">about</a></li>
</ul>
<ui-view></ui-view>
</body>
angular.module('myApp', ['ui.router'])
.config(function ($stateProvider) {
var helloState = {
name: 'hello',
url: '/hello',
template: '<h3>hello world</h3>'
};
var aboutState = {
name: 'about',
url: '/about',
template: '<h3>this is a abut view</h3>'
};
$stateProvider.state(helloState)
.state(aboutState);
});
我們首先來談談HTML部分的代碼。其中首先來看看ui-sref
、ui-sref-active
屬性和ui-view
標籤。
ui-sref:
ui-sref: 是用來連接狀態的一個指令。
這是一個可以帶參數的連接狀態的指令。當被選中,這個指令會激活帶有提供的參數值的連接狀態。Linked State
屬性值是連接狀態的name
比如:
在上面的代碼中,<a ui-sref="hello" ui-sref-active="active">hello</a>
其中
ui-sref
的屬性值hello
,對應的就是js中helloState
的name
值。Relative Links
你也可以在
ui-sref
中使用相對狀態路徑。
需要注意的是路徑是相對於創建了連接的狀態。這允許一個狀態創建一個總是命中相同目的的相對ui-sref
屬性。
例子:
下面的連接都相對於於父狀態,即使當一個子狀態當前被激活<a ui-sref='.child1'>child 1 state</a> <a ui-sref='.child2'>child 2 state</a>
下面的連接會激活父狀態
<a ui-sref='^'>Return</a>
這個例子是個很不錯的例子
Relative linkshrefs
如果這個已連接的狀態有一個URL,指令會自動生成並且更新
href
屬性(使用[[StateService.href]])方法。
例子:
假設users
狀態有一個url/users/
<a ui-sref='users' href='/users/'>Users</a>
參數值
除了狀態名,屬性
ui-sref
可以包含用來激活狀態的參數值。參數值可以添加在狀態名之後,用括號閉合。括號內的內容是一個表達式,被當作參數值執行。
例子:
這個例子渲染了一個連接列表給用戶,狀態的userId
參數值來自用戶的user.id
屬性。<li ng-repeat="user in users"> <a ui-sref="users.detail({userId: user.id})">{{user.displayName}}</a> </li>
注意:
參數值表達式通過$watch
監聽並更新。過渡期選項(Transition Options)
你可以通過
ui-sref-opts
屬性來指定[[TransitionOptions]]
傳遞給[[StateService.go]]
。
選項被限制爲只有location
,inhreit
並且reload
。例子:
<a ui-sref="home" ui-sref-opts="{reload: true}">Home</a>
其他DOM事件
你可以指定DOM事件響應(而不是click),通過提供一個
events
數組在ui-sref-opts
屬性中。
例子:<input type="text" ui-sref="contacts" ui-sref-opts="{events: ['change', 'blur']}">
跟參數值表達式不一樣的是,狀態名沒有通過
$watch
進行監聽(因爲性能原因),如果你需要動態更新連接狀態,使用全動態指定[[uiState]]指令
。
ui-view
ui-view: 一個用激活狀態填充視區的指令。
Attributes
name: (可選的) 視圖名稱
相同狀態下的視圖中的視圖名稱必須是唯一的。在不同的狀態下你可以有相同的名稱。
autoScroll
一個表達式,當執行結果爲
true
, 狀態被激活時,ui-view
將會滾動進試圖中。通過[[$uiViewScroll]]
來實現滾動。onload
當視圖更新時就會執行的表達式
其中ui-view
組件使用ViewConfig
來決定哪個視圖被加載進ui-view
,並且決定了視圖狀態的上下文對象。比如:
<div ng-app="myApp">
<a ui-sref="hello">hello</a>
<div ui-view></div>
</div>
angular.module('myApp')
.config(['$stateProvider', function($stateProvider) {
var helloState = {
name:'hello',
url: '/hello',
template: '<h2>{{$resolve.init}}</h2><h3>hello world {{num}}</h3><button ng-click="helloCtrl.add()">+</button><button ng-click="helloCtrl.subtract()">-</button>',
controller: function ($scope) {
$scope.num = 0;
this.add = function () {
$scope.num++;
}
this.subtract = function () {
$scope.num--;
}
},
controllerAS: "helloCtrl",
resolve: {
init: function () {
console.log('init');
return 1;
}
}
};
$stateProvider.state(helloState);
}])
上面是一個較爲完整的例子。a
標籤中的ui-sref
的值與viewConfig
的name
對應。需要注意的是,resolve
塊中的數據作爲$scope
放置在scope
中(上面的模板中提到寫到的<h2>{{$resolve.init}}</h2>
)。
此時,將$scope
輸出到控制檯中, 發現了$resolve
。其中$resolve
下$transitions$
有各種狀態的hookRegistrationFn
$transition$: Transition
$id: 0
isActive: ƒ ()
onBefore: ƒ hookRegistrationFn(matchObject, callback, options)
onEnter: ƒ hookRegistrationFn(matchObject, callback, options)
onError: ƒ hookRegistrationFn(matchObject, callback, options)
onExit: ƒ hookRegistrationFn(matchObject, callback, options)
onFinish: ƒ hookRegistrationFn(matchObject, callback, options)
onRetain: ƒ hookRegistrationFn(matchObject, callback, options)
onStart: ƒ hookRegistrationFn(matchObject, callback, options)
onSuccess: ƒ hookRegistrationFn(matchObject, callback, options)
注:上面的例子中,在controller
部分加上console.log(1)
,發現控制檯中的輸出爲init
,然後是1
。