angular的uiRouter服務學習(3)

詩&遠方發表於2014-12-26

本篇接著上一篇 angular的uiRouter服務學習(2) 繼續講解uiRouter的用法

本篇主要講解uiRouter的多個命名的檢視

 

我們可以給ui-view元素新增ui-view的值來給它命名,這樣,一個檢視模板裡就可以有多個ui-view標籤.

比如下面這個應用,它需要動態的填充一個圖表,圖表裡有一些表格資料,篩選項,等:

給檢視命名,需要在狀態裡定義views屬性. views的屬性值為一個物件.

 

views屬性會覆蓋template屬性:

如果給狀態定義了views屬性,那麼狀態的template,templateUrl,templateProvider將會被無視掉. 考慮這種場景: 一個父檢視模板,裡面需要包含多個不同的檢視. 在這種情況下,可以定義一個抽象狀態來充當父狀態,然後在子狀態裡定義views屬性.

 

栗子-name匹配:

views物件裡的屬性名應該和ui-view元素裡面的值所對應,像下面這樣: 

html:

<div>
  <a href="report">檢視檢視</a>
  <div ui-view></div>
  <div ui-view="filters"></div>
  <div ui-view="tabledata"></div>
  <div ui-view="graph"></div>
</div>

js:

var named = angular.module('namedView',['ui.router']);

var report = {
    name:'report',
    url:'/report',
    views:{
        'filters':{
            templateUrl:'report-filters.html',
            controller:function($scope){
                $scope.title="我是filters的內容"
            }
        },
        'tabledata':{
            templateUrl:'report-table.html',
            controller:function($scope){
                $scope.title="我是table的內容"
            }
        },
        'graph':{
            templateUrl:'report-graph.html',
            controller:function($scope){
                $scope.title="我是graph的內容"
            }
        }
    }
};

named.config(function($locationProvider,$stateProvider){
    $locationProvider.html5Mode({enabled:true}).hashPrefix('!');
    $stateProvider.state(report)
});

report-filters.html,report-graph.html,report-table.html:

<h3>{{title}}</h3>

點選'檢視檢視'啟用report狀態:

可以看到,report狀態被啟用後,它有三個ui-view,不同的ui-view有不同的名字,然後通過定義狀態的views屬性來分別給三個ui-view定義templateUrl,controller.

 

檢視名-相對名字和絕對名字:

views物件的檢視名,有兩種取法,一種是相對名字,一種是絕對名字.剛才我們看到的例子是絕對名字.如果是相對名字的話,要符合 viewname@statename 這種格式. 其中,viewname就是檢視中ui-view屬性值; statename是狀態名. 連起來就是:在statename狀態下,尋找ui-view屬性值為對應viewname的元素. 

還需要注意一點,viewname可以使用'-'分割的名字,但和指令不同,在js程式碼裡不需要把'-'轉換成駝峰命名的格式,而是保持'-'分割的名字就可以了.

比如上面的例子,我們可以把它寫成相對名字:

views:{
        'filters@':{
            ...
            }
        },
        'tabledata@':{
            ...
            }
        },
        'graph@':{
            ...
            }
        }
}

這樣,檢視名就變成了相對名字,這裡statename為空,表示根狀態,也就是起始html頁面.

相對名字可以做一些很強大的檢視匹配.比如下面這樣一個例子:

named-views.html:

<div>
  <a href="report">檢視檢視</a>
  <a href="report/detail">檢視子檢視</a>
  <div ui-view>沒有ui-view值</div>
  <div ui-view="aaa">ui-view值為aaa</div>
</div>

js:

var named = angular.module('namedView',['ui.router']);
var report = {
    name:'report',
    url:'/report',
    templateUrl:'report.html'
};
var detail = {
    name:'report.detail',
    url:'/detail',
    parent:'report',
    views:{
        //絕對名字:在父狀態的template(也就是report.html)裡尋找對應名字為'aaa'的ui-view元素
        'aaa':{
            templateUrl:'aaa.html'
        },
        
//絕對名字:在父狀態的template(也就是report.html)裡尋找沒有名字的ui-view元素 '':{ templateUrl:'report.detail.html' },
/*

'aaa@report':{ templateUrl:'aaa.html' }, '@report':{ templateUrl:'report.detail.html' },
*/
//相對名字:在report.detail狀態裡尋找對應名字為'bbb'的ui-view元素 'bbb@report.detail':{ templateUrl:'bbb.html' }, //相對名字:在report.detail狀態裡尋找對應沒有名字的ui-view元素 '@report.detail':{ templateUrl:'no-name.html' },
//相對名字:在report狀態裡尋找對應名字為'bbb'的ui-view元素 'bbb@report':{ templateUrl:'bbb2.html' }, //相對名字:在根狀態(named-views.html)裡尋找對應名字為'aaa'的ui-view元素 'aaa@':{ templateUrl:'aaa2.html' },
//相對名字:在根狀態(named-views.html)裡尋找沒有名字的ui-view元素. //需要特別注意:這裡等於是在子狀態裡定義了父狀態的裡ui-view,要這樣寫的話,最開始的兩段絕對名字'aaa'和'',就必須改成下面註釋的兩段相對名字'aaa@report'和'bbb@report'. //否則會造成錯誤. /*
'@':{ templateUrl:'report.html' }
*/ } }; named.config(function($locationProvider,$stateProvider){ $locationProvider.html5Mode({enabled:true}).hashPrefix('!'); $stateProvider.state(report).state(detail) });

report.html:

<h1>report.html:</h1>
<div>
  <h2>ui-view值為空的內容:</h2>
  <div ui-view></div>
</div>
<div>
  <h2>ui-view值為'aaa'的內容:</h2>
  <div ui-view="aaa"></div>
</div>
<div>
  <h2>ui-view值為'bbb'的內容:</h2>
  <div ui-view="bbb"></div>
</div>

report.detail.html:

<h3>report.detail.html:</h3>
<div>
  <h4>ui-view值為空的內容:</h4>
  <div ui-view></div>
</div>
<div>
  <h4>ui-view值為'bbb'的內容:</h4>
  <div ui-view="bbb"></div>
</div>

aaa.html:

<h3>aaa.html:</h3>

bbb.html:

<h5>bbb.html</h5>

aaa2.html:

<h1>aaa2.html:</h1>

bbb2.html:

<h3>bbb2.html</h3>

no-name.html:

<h5>no-name.html</h5>

點選'檢視檢視':

點選'檢視子檢視':

 

下面分析一下檢視的載入:

1.當進入report狀態時,會用report.html來填充named-views.html裡面的ui-view元素. (ui-view="aaa")不會被填充

2.進入report狀態的子狀態:report.detail狀態.

  (1)'aaa': 絕對名字,在父狀態的檢視模板裡尋找對應名字為'aaa'的ui-view元素. 然後使用'aaa.html'來填充它.

  (2)'': 絕對名字,在父狀態的檢視模板裡尋找沒有名字的ui-view元素.然後使用'report.detail.html'來填充它.

  (3)'aaa@report': 相對名字,在report狀態裡尋找對應名字為'aaa'的ui-view元素. 然後使用'aaa.html'來填充它.

  (4)'@report': 相對名字,在report狀態裡尋找沒有名字的ui-view元素.然後使用'report.detail.html'來填充它.

       * 注意,(1)(2)和(3)(4),一個是絕對,一個是相對,但其實都是在report狀態裡尋找.它們兩者的區別最後會說到.

  (5)'bbb@report.detail': 相對名字,在report.detail狀態裡尋找對應名字為'bbb'的ui-view元素.然後使用'bbb.html'來填充它.

  (6)'@report.detail': 相對名字,在report.detail狀態裡尋找沒有名字的ui-view元素.然後使用no-name.html來填充它.

  (7)'bbb@report': 相對名字,在report狀態裡尋找對應名字為'bbb'的ui-view元素,然後使用'bbb2.html'來填充它.

  (8)'aaa@': 相對名字,@後面為空,就表示在根狀態(也就是named-views.html)裡尋找對應名字為aaa的ui-view元素,然後使用'aaa2.html'來填充它

  (9)'@': 相對名字, 表示在根狀態(也就是named-views.html)裡尋找沒有名字的ui-view元素,然後使用'report.html'來填充它.

  (9)的填充方式,和1的填充,從檢視匹配的角度來說,是完全一致的,都是在named-views.html裡尋找沒有名字的ui-view元素,然後用同一個模板來填充它.但是,從使用的角度來說,他們是不同的.

  就拿這個栗子來說: 我這裡是把'@'給註釋掉了,因為一旦使用了'@',那麼(1)(2)'aaa'''這兩個絕對名字,會找不到他們父狀態的檢視模板.因為他們父狀態的檢視模板是通過相對名字來定義的.這個時候,如果要用'@',就必須使用(3)(4)'aaa@report''@report'.

  *總結來說,絕對名字和相對名字,在一個狀態裡最好不要混用.

 

完整程式碼:https://github.com/OOP-Code-Bunny/angular/tree/master/uiRouter

參考原文:https://github.com/angular-ui/ui-router/wiki/Multiple-Named-Views

 

相關文章