iT邦幫忙

DAY 13
0

我在前端 ng 時系列 第 13

ui-router - 巢狀頁面

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 解說


上一篇
初談 ui-router
下一篇
ui-router - 監聽事件
系列文
我在前端 ng 時30

尚未有邦友留言

立即登入留言