ui-router 的一大優點是 nested view。
ui-router 的 nested view 是 state 存有親子關係。
子(children state)可以繼承父母 ( parent ) 的 resolve function 跟 data。
不同的 children state 都會繼承 parent 資源。
所以 parent 適合處理共用的資源,然後讓 children 處理不同 state 的資源。(官網解說)
// 定義 parent $state
$stateProvider
.state('home', {
url: '/home’,
data: {
parentData: ‘parent data’;
},
resolve: {
parentData: function () {
console.log('parent data');
return 'here is parent resolve function';
}
},
/..../
.state(‘home.child’ {
// 完整 url 會是 /home/child
url: ‘/child’,
// 繼承 home resolve function (DI)
controller: function ($state, parentResolve) {
// 從 $state.current.data 獲取 data
$scope.pd = $state.current.data.parentData; // output: ‘parent data'
console.log(parentData); // output: 'here is parent resolve function'
}
})
注意假如 children 定義的 resolve 或 data 名稱跟 parent 定義的相同,
在 children 中取得的資料是 children 的,parent 資源被取代掉了。官網範例
ui-router 還有很強大的 multiple named views 的概念。
可在頁面上定義好幾個 ui-view,然後分別取名字。
當 state 定義的時候,可以指定該 state 是出現在那些 ui-view,而哪些 ui-router 保持不動。
簡單的範例:
範例中,我定義三種 ui-view: Header title、Sidebar 跟 Content。
Header 跟 Content 會隨者 state 變化,而 Sidebar 只有在常見問題頁面才會變更。
需要在頁面上先定義 ui-view 的 element。(注意名稱不能相同)
<!— ‘主頁’ 是 ui-view=title ,’主頁’ 是預設內容—>
<h2 ui-view="title">主頁</h2>
<div class="row">
<div class="small-4 large-5 columns" ui-view="sidebar”>
<!-- 主頁的 sidebar nested view 的地方-->
</div>
<div class="small-8 large-7 columns content" ui-view="content">
<!-- 主頁的 nested view 的地方-->
</div>
</div>
在 $state.view 中設定對應的 template, resolve, controller。
注意,跟 nested view 一樣,要取代遠本的 view ,該 state 一定要有親子關係。
// 定義 parent $state
$stateProvider
.state('home', {
url: '/home',
data: {
parentData: 'parent data'
},
resolve: {
parentResolve: function () {
return 'here is parent resolve function data';
}
},
views: {
// 此 state 的主要 view
'': {
templateUrl: 'main.html'
},
// template for ui-view=sidebar
// sidebar 是 view 的名稱 + '@' + state 名稱
'sidebar@home':{
templateUrl: 'sidebar.html'
},
// template for ui-view=content
'content@home': {
template: '<div>在主頁的 content</div>'
}
}
})
// nested routing, 在 parent state 後面接 '.' 加 children state name
.state('home.onePiece', {
// 前面會加上 parent state 的 url, ex: /home/piece/2
url: '/piece/:id',
views: {
// 可以 override parent state 的指定 ui-view
'title@home' : {
template: '<div>one piece 頁面</div>'
},
'content@home' : {
template: '<div>我在介紹 {{name}}</div>',
controller: function ($scope, $stateParams) {
$scope.id = $stateParams.id;
switch ($scope.id) {
case 1:
$scope.name = '魯夫';
break;
case 2:
$scope.name = '索隆';
break;
}
}
}
}
})
// 一定要是在 children 才可以替換在 parent 的 view
.state('qa', {
// absolute routes (^)
url: '^/questions',
// 可以用 '.' 或 parent 定義 parent state
parent: 'home',
views: {
'title@home' : {
template: '<div>常見問題</div>'
},
'sidebar@home':{
templateUrl: 'qSidebar.html'
},
'content@home': {
template: '<div>常見問題的 content</div><div>{{pd}}</div><div>{{pr}}</div>',
// 繼承 home resolve function (DI)
controller: function ($scope, $state, parentResolve) {
// 從 $state.current.data 獲取 data
$scope.pd = $state.current.data.parentData;
$scope.pr = parentResolve;
}
}
}
});
範例:http://plnkr.co/edit/ZvKrDXuPIWpl4a3U0Jfy?p=preview
nested view 搭配 angularjs animation css 的 ng-enter 跟 ng-leave 就可以輕易地做到 官網範例 的效果~
官網 animation 解說