本篇接著上一篇 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