angularJs模塊ui-router之狀態嵌套和視圖嵌套

原文地址:http://bubkoo.com/2014/01/01/angular/ui-router/guide/nested-states%20&%20nested-views/html

狀態嵌套的方法

狀態能夠相互嵌套。有三個嵌套的方法:ide

  1. 使用「點標記法」,例如:.state('contacts.list', {})
  2. 使用parent屬性,指定一個父狀態的名稱字符串,例如:parent: 'contacts'
  3. 使用parent屬性,指定一個父狀態對象,例如:parent: contacts(contacts 是一個狀態對象)

點標記法

$stateProvider中可使用點語法來表示層次結構,下面,contacts.listcontacts的子狀態。函數

$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屬性
    除了這些,沒有其餘屬性繼承下來(好比controllerstemplatesurl等)

繼承解決的依賴項

版本 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!"
})
複製代碼

 

Abstract States 抽象狀態

一個抽象的狀態能夠有子狀態但不能顯式激活,它將被隱性激活當其子狀態被激活時。

下面是一些你將可能會使用到抽象狀態的示例:

  • 爲全部子狀態預提供一個基url
  • 在父狀態中設置template屬性,子狀態對應的模板將插入到父狀態模板中的ui-view(s)
  • 經過resolve屬性,爲全部子狀態提供解決依賴項
  • 經過data屬性,爲全部子狀態或者事件監聽函數提供自定義數據
  • 運行onEnteronExit函數,這些函數可能在以某種方式修改應用程序。
  • 上面場景的任意組合

請記住:抽象的狀態模板仍然須要<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>
相關文章
相關標籤/搜索