2、Angular-Ui Router 嵌套狀態和嵌套視圖


Methods for Nesting States
嵌套狀態的方法

States can be nested within each other. There are several ways of nesting states:
狀態可以相互嵌套,嵌套狀態有幾種方法:

  1. Using 'dot notation'. For example .state('contacts.list', {}).
    使用“點記法”。例如, .state('contacts.list', {})。
  2. Use the ui-router.stateHelper to build states from a nested state tree. Courtesy of @marklagendijk. 
    使用ui-router.stateHelper從嵌套狀態樹建立狀態。感謝@marklagendijk的貢獻。
  3. Using the parent property with the parent name as string. For example: parent: 'contacts'
    使用父屬性與父名字符串。例如:parent: 'contacts'
  4. Using the parent property with the parent object. For example parent: contacts (where 'contacts' is a stateObject)
    使用父屬性與父對象值一起使用。例如parent: contacts(“contacts”是一個狀態對象)

Dot Notation
點記法

You can use dot syntax to infer your hierarchy to the $stateProvider. Below, contacts.listbecomes a child of contacts.
您可以使用點語法來推斷您的$stateProvider層次結構。下面的contacts.list變成了contacts的子狀態。

$stateProvider
  .state('contacts', {})
  .state('contacts.list', {});

stateHelper module
stateHelper模塊

This is a 3rd party module created by @marklagendijk. So you have to include it in addition to ui-router. Visit the stateHelper repo to learn more
這是由@marklagendijk創建的第三方模塊。所以你必須在ui-router之外加上它。訪問stateHelper瞭解更多信息

angular.module('myApp', ['ui.router', 'ui.router.stateHelper'])
  .config(function(stateHelperProvider){
    stateHelperProvider.state({
      name: 'root',
      templateUrl: 'root.html',
      children: [
        {
          name: 'contacts',
          templateUrl: 'contacts.html',
          children: [
            {
              name: 'list',
              templateUrl: 'contacts.list.html'
            }
          ]
        },
        {
          name: 'products',
          templateUrl: 'products.html',
          children: [
            {
              name: 'list',
              templateUrl: 'products.list.html'
            }
          ]
        }
      ]
    });
  });

Parent Property using State Name String
使用狀態名稱的父屬性

Alternately, you can specify the parent of a state via the parent property.
您可以通過父屬性指定狀態的父狀態。

$stateProvider
  .state('contacts', {})
  .state('list', {
    parent: 'contacts'
  });

Object-based States
基於對象的狀態

If you aren't fond of using string-based states, you can also use object-based states. The nameproperty goes in the object and the parent property must be set on all child states, like this:
如果您不喜歡使用基於字符串的狀態,那麼也可以使用基於對象的狀態。name屬性在對象中,父屬性必須在所有子節點上設置,如下:

var contacts = { 
    name: 'contacts',
    templateUrl: 'contacts.html'
}
var contactsList = { 
    name: 'list',
    parent: contacts,
    templateUrl: 'contacts.list.html'
}

$stateProvider
  .state(contacts)
  .state(contactsList)

You can usually reference the object directly when using other methods and property comparisons:
在使用其他方法或屬性比較時, 通常可以直接引用該對象:

$state.transitionTo(states.contacts);
$state.current === states.contacts;
$state.includes(states.contacts)

Registering States Order
註冊狀態順序

You can register states in any order and across modules. You can register children before the parent state exists. It will queue them up and once the parent state is registered then the child will be registered.
您可以按任意順序和跨模塊註冊狀態。您可以在父狀態存在之前註冊子狀態。它將對它們進行排隊, 一旦註冊了父狀態, 就會註冊該父狀態的子狀態。

Parent MUST Exist
父狀態必須存在

If you register only a single state, like contacts.list, you MUST define a state called contacts at some point, or else no states will be registered. The state contacts.list will get queued until contacts is defined. You will not see any errors if you do this, so be careful that you define the parent in order for the child to get properly registered.
如果只註冊單個狀態 (如 "contacts.list"), 則必須在某個點定義一個稱爲 "contacts" 的狀態, 否則將不註冊任何狀態。狀態contacts.list將被排入隊列, 直到定義了contacts狀態。如果您沒有定義contacts狀態, 您將看不到任何錯誤, 因此請謹慎地定義父狀態, 以便使子狀態正確註冊。

Naming Your States
命名您的狀態

No two states can have the same name. When using dot notation the parent is inferred, but this doesn't change the name of the state. When explicitly providing a parent using the parentproperty, state names still must be unique. For example, you can't have two different states named "edit" even if they have different parents.

Nested States & Views
嵌套狀態&視圖

When the application is in a particular state—when a state is "active"—all of its ancestor states are implicitly active as well. Below, when the "contacts.list" state is active, the "contacts" state is implicitly active as well, because it's the parent state to "contacts.list".
當應用程序狀態處於“活動狀態”時,其所有的祖先狀態也都是隱式的活動。下面,當“contacts.list”狀態是活動的,“contacts”狀態也是隱式活動的,因爲它是“contacts.list”的父狀態。

Child states will load their templates into their parent's ui-view.
子狀態將把它們的模板加載到父視圖中。

完整示例請參見: http://plnkr.co/edit/7FD5Wf?p=preview

$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>

What Do Child States Inherit From Parent States?
子狀態從父狀態那裏繼承了什麼?

Child states DO inherit the following from parent states:
子狀態從父狀態繼承以下內容:

Nothing else is inherited (no controllers, templates, url, etc). However, children of abstract states do inherit the url property of their parent as a prefix of their own url.
除此之外沒有別的東西可繼承 (包括控制器、模板、url 等)。然而, 抽象狀態的子狀態確實繼承其父狀態的 url 屬性作爲其自己的 url 的前綴。

Inherited Resolved Dependencies
繼承的解析依賴關係

New in version 0.2.0

Child states will inherit resolved dependencies from parent state(s), which they can overwrite. You can then inject resolved dependencies into the controllers and resolve functions of child states.
子狀態將從父狀態(s)繼承已解析的依賴項,它們可以覆蓋這些依賴項。然後,您可以將解析的依賴項注入控制器,並解析子狀態的函數。

$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;
      }

NOTE
注意
:

  • The resolve keyword MUST be relative to state not views (in case you use multiple views).
    解析關鍵字必須是相對於狀態而不是視圖(以防您使用多個視圖)。
  • If you want a child resolve to wait for a parent resolve, you should inject the parent resolve keys into the child. (This behavior is different in ui-router 1.0).
    如果您希望一個子解析等待父解析,那麼您應該將父解析注入到子解析中。(這種行爲在ui-router 1.0中是不同的)。

Inherited Custom Data
繼承自定義數據

Child states will inherit data properties from parent state(s), which they can overwrite.
子狀態將從父狀態繼承數據屬性, 子狀態可以覆蓋它們。

$stateProvider.state('parent', {
      data:{
         customData1:  "Hello",
         customData2:  "World!"
      }
   })
   .state('parent.child', {
      data:{
         // customData1 inherited from 'parent'
         // but we'll overwrite customData2
         customData2:  "UI-Router!"
      }
   });

$rootScope.$on('$stateChangeStart', function(event, toState){ 
    var greeting = toState.data.customData1 + " " + toState.data.customData2;
    console.log(greeting);

    // Would print "Hello World!" when 'parent' is activated
    // Would print "Hello UI-Router!" when 'parent.child' is activated
})

Scope Inheritance by View Hierarchy Only
僅按視圖層次結構範圍繼承

Keep in mind that scope properties only inherit down the state chain if the views of your states are nested. Inheritance of scope properties has nothing to do with the nesting of your states and everything to do with the nesting of your views (templates).
請記住,如果您的狀態的視圖是嵌套的,那麼範圍屬性只繼承狀態鏈。範圍屬性的繼承與您的狀態的嵌套無關,與您的視圖的嵌套(模板)有關。

It is entirely possible that you have nested states whose templates populate ui-views at various non-nested locations within your site. In this scenario you cannot expect to access the scope variables of parent state views within the views of children states.
您可能有嵌套的狀態,它們的模板在您的站點內的不同的非嵌套位置填充ui-view。在這個場景中,您不能期望在子狀態視圖中訪問父狀態視圖的範圍變量。

View Inherited Resolved Dependencies
視圖繼承已解析的依賴項

Views may inherit resolved dependencies from the state that they belong to, but may not inherit those of their sibling views.
視圖可以從它們所屬的狀態繼承已解析的依賴項,但可能不會繼承它們的兄弟視圖。

$stateProvider.state('myState', {
  resolve:{
     resMyState:  function(){
        return { value: 'mystate' };
     }
  },
  views: {
    'foo@myState': {
      templateUrl: 'mystate-foo.html',
      controller: function($scope, resMyState, resFoo){ 
        /* has access to resMyState and resFoo,
           but *not* resBar */ 
      },
      resolve: {
        resFoo: function() {
          return { value: 'foo' };
        }
      },
    },
    'bar@myState': {
      templateUrl: 'mystate-bar.html',
      controller: function($scope, resMyState, resBar){ 
        /* has access to resMyState and resBar,
           but *not* resFoo */ 
      },
      resolve: {
        resBar: function() {
          return { value: 'bar' };
        },
      },
    },
  },
});

Abstract States
抽象狀態

An abstract state can have child states but can not get activated itself. An 'abstract' state is simply a state that can't be transitioned to. It is activated implicitly when one of its descendants are activated.
抽象狀態可以有子狀態,但不能被激活。一個“抽象”的狀態就是一個不能被主動激活的狀態。當它的一個後代被激活時,它會被隱式激活。

Some examples of how you might use an abstract state are:
一些關於如何使用抽象狀態的例子是:

  • To prepend a url to all child state urls.
    將 url 預置爲所有子狀態 url。
  • To insert a template with its own ui-view(s) that its child states will populate.
    要將子狀態插入自己的ui-view(s)的模板。
    • Optionally assign a controller to the template. The controller must pair to a template.
      (可選) 將控制器分配給模板。控制器必須與模板配對。
    • Additionally, inherit $scope objects down to children, just understand that this happens via the view hierarchy, not the state hierarchy.
      另外,將$scope對象繼承給子對象,只需要知道這是通過視圖層次結構而不是狀態層次結構來實現的。
  • To provide resolved dependencies via resolve for use by child states.
    通過解析(Resolve)爲子狀態提供依賴關係。
  • To provide inherited custom data via data for use by child states or an event listener.
    通過數據爲子狀態或事件監聽器提供可繼承的自定義數據。
  • To run an onEnter or onExit function that may modify the application in someway.
    運行一個onEnter或onExit函數,它可以以某種方式修改應用程序。
  • Any combination of the above.
    以上的任何組合。

Remember: Abstract states still need their own <ui-view/> for their children to plug into. So if you are using an abstract state just to prepend a url, set resolves/data, or run an onEnter/Exit function, then you'll additionally need to set template: "<ui-view/>".
請記住:抽象的狀態仍然需要他們自己的孩子去插入。因此,如果您正在使用一個抽象的狀態來預先設置一個url,設置resolves/data,或者運行一個onEnter/Exit函數,那麼您還需要設置模板:“”。

Abstract State Usage Examples:
抽象狀態用法示例:

To prepend url to child state urls
將 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
    })

To insert a template with its own ui-view for child states to populate
要插入一個帶有自己的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>

Combination
組合

Shows prepended url, inserted template, paired controller, and inherited $scope object.
顯示預先輸入的url、插入的模板、成對的控制器和繼承的$scope對象。

完整示例請參見: 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>

需要命理預測服務請加微信:


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章