原文地址:http://bubkoo.com/2014/01/01/angular/ui-router/guide/nested-states%20&%20nested-views/html
狀態能夠相互嵌套。有三個嵌套的方法:ide
.state('contacts.list', {})
parent
屬性,指定一個父狀態的名稱字符串,例如:parent: 'contacts'
parent
屬性,指定一個父狀態對象,例如:parent: contacts
(contacts 是一個狀態對象)在$stateProvider
中可使用點語法來表示層次結構,下面,contacts.list
是contacts
的子狀態。函數
$stateProvider .state('contacts', {}) .state('contacts.list', {});
parent
屬性,指定一個父狀態的名稱字符串$stateProvider .state('contacts', {}) .state('list', { parent: 'contacts' });
若是你不喜歡使用基於字符串的狀態,您還可使用基於對象的狀態。name
屬性將在狀態對象內部設置,在全部的子狀態對象中設置parent
屬性爲父狀態對象,像下面這樣:ui
var contacts = { name: 'contacts', //mandatory templateUrl: 'contacts.html' } var contactsList = { name: 'list', //mandatory parent: contacts, //mandatory templateUrl: 'contacts.list.html' } $stateProvider .state(contacts) .state(contactsList)
$state.transitionTo(states.contacts);在方法調用和屬性比較時能夠直接引用狀態對象:url
$state.current === states.contacts; $state.includes(states.contacts)
註冊狀態的順序spa
能夠以任何順序和跨模塊註冊狀態,也能夠在父狀態存在以前註冊子狀態。一旦父狀態被註冊,將觸發自動排序,而後註冊子狀態。code
狀態不容許重名,當使用「點標記法」,parent
屬性被推測出來,但這並不會改變狀態的名字;當不使用「點標記法」時,parent
屬性必須明確指定,但你仍然不能讓任何兩個狀態有相同的名稱,例如你不能有兩個不一樣的狀態命名爲」edit」,即便他們有不一樣的父狀態。router
當應用程序在一個特定的狀態 - 當一個狀態是活動狀態時 - 其全部的父狀態都將成爲活躍狀態。下面例子中,當」contacts.list」是活躍狀態時,」contacts」也將隱性成爲活躍狀態,由於他是」contacts.list」的父狀態。htm
子狀態將把其對應的模板加載到父狀態對應模板的ui-view
中。對象
$stateProvider .state('contacts', { templateUrl: 'contacts.html', controller: function($scope){ $scope.contacts = [{ name: 'Alice' }, { name: 'Bob' }]; } }) .state('contacts.list', { templateUrl: 'contacts.list.html' }); function MainCtrl($state){ $state.transitionTo('contacts.list'); }
<!-- index.html --> <body ng-controller="MainCtrl"> <div ui-view></div> </body>
<!-- contacts.html --> <h1>My Contacts</h1> <div ui-view></div>
<!-- contacts.list.html --> <ul> <li ng-repeat="contact in contacts"> <a>{{contact.name}}</a> </li> </ul>
子狀態將從父狀態繼承哪些屬性?
子狀態將從父母繼承如下屬性:
data
屬性controllers
、templates
和url
等)版本 v0.2.0 的新特性
子狀態將從父狀態繼承經過解決器解決的依賴注入項,而且能夠重寫(overwrite)依賴項,能夠將解決依賴項注入子狀態的控制器和解決函數中。
$stateProvider.state('parent', { resolve:{ resA: function(){ return {'value': 'A'}; } }, controller: function($scope, resA){ $scope.resA = resA.value; } }) .state('parent.child', { resolve:{ // 將父狀態的解決依賴項注入到子狀態的解決函數中 resB: function(resA){ return {'value': resA.value + 'B'}; } }, // 將父狀態的解決依賴項注入到子狀態的控制器中 controller: function($scope, resA, resB){ $scope.resA2 = resA.value; $scope.resB = resB.value; }
繼承自定義data
屬性值
子狀態將從父狀態繼承自定義data
屬性值,而且能夠重寫(overwrite)data
屬性值
$stateProvider.state('parent', { data:{ customData1: "Hello", customData2: "World!" } }) .state('parent.child', { data:{ // customData1 inherited from 'parent' // 覆蓋了 customData2 的值 customData2: "UI-Router!" } }); $rootScope.$on('$stateChangeStart', function(event, toState){ var greeting = toState.data.customData1 + " " + toState.data.customData2; console.log(greeting); // 'parent'被激活時,輸出 "Hello World!" // 'parent.child'被激活時,輸出 "Hello UI-Router!" })
一個抽象的狀態能夠有子狀態但不能顯式激活,它將被隱性激活當其子狀態被激活時。
下面是一些你將可能會使用到抽象狀態的示例:
template
屬性,子狀態對應的模板將插入到父狀態模板中的ui-view(s)
中resolve
屬性,爲全部子狀態提供解決依賴項data
屬性,爲全部子狀態或者事件監聽函數提供自定義數據onEnter
或onExit
函數,這些函數可能在以某種方式修改應用程序。請記住:抽象的狀態模板仍然須要<ui-view/>
,來讓本身的子狀態模板插入其中。所以,若是您使用抽象狀態只是爲了預提供基url、提供解決依賴項或者自定義data、運行onEnter/Exit函數,你任然須要設置template: "<ui-view/>"
。
爲子狀態提供一個基url,子狀態的url是相對父狀態的
$stateProvider .state('contacts', { abstract: true, url: '/contacts', // Note: abstract still needs a ui-view for its children to populate. // You can simply add it inline here. template: '<ui-view/>' }) .state('contacts.list', { // url will become '/contacts/list' url: '/list' //...more }) .state('contacts.detail', { // url will become '/contacts/detail' url: '/detail', //...more })
將子狀態模板插入到父狀態指定的ui-view
中
$stateProvider .state('contacts', { abstract: true, templateURL: 'contacts.html' ) .state('contacts.list', { // loaded into ui-view of parent's template templateUrl: 'contacts.list.html' }) .state('contacts.detail', { // loaded into ui-view of parent's template templateUrl: 'contacts.detail.html' })
<!-- contacts.html --> <h1>Contacts Page</h1> <div ui-view></div>
完整示例:http://plnkr.co/edit/gmtcE2?p=preview組合使用示例
$stateProvider .state('contacts', { abstract: true, url: '/contacts', templateUrl: 'contacts.html', controller: function($scope){ $scope.contacts = [{ id:0, name: "Alice" }, { id:1, name: "Bob" }]; } }) .state('contacts.list', { url: '/list', templateUrl: 'contacts.list.html' }) .state('contacts.detail', { url: '/:id', templateUrl: 'contacts.detail.html', controller: function($scope, $stateParams){ $scope.person = $scope.contacts[$stateParams.id]; } })
<!-- contacts.html --> <h1>Contacts Page</h1> <div ui-view></div>
<!-- contacts.list.html --> <ul> <li ng-repeat="person in contacts"> <a ng-href="#/contacts/{{person.id}}">{{person.name}}</a> </li> </ul>
<!-- contacts.detail.html --> <h2>{{ person.name }}</h2>