首页 > 代码库 > angular的uiRouter服务学习(2)
angular的uiRouter服务学习(2)
本篇接着上一篇 angular的uiRouter服务学习(1) 继续讲解uiRouter的用法
本篇主要讲解uiRouter的嵌套状态&嵌套视图
嵌套状态的方法:
状态和状态之间可以互相嵌套,状态的嵌套共有以下几种方式:
1.使用‘.state()‘进行嵌套. 比如 .state(‘contact‘,{}).state(‘contact.list‘,{})
2.使用 ui-router.stateHelper 来创建状态嵌套树. 这种方式需要另外引入依赖,所以很少被使用.也就不具体详解了
3.定义状态的‘parent‘属性,属性值是一个字符串,就是父状态的名字.比如 {parent:‘contacts‘}
4.定义状态的‘parent‘属性,属性值是一个对象,对象就是父状态对象.比如 {parent:contacts}
使用.state()来创建嵌套状态:
可以对$stateProvider使用.state()来指定状态的嵌套继承,比如下面的例子:contacts.list就是contacts的一个子状态:
html:
<div> <a href="contacts">查看视图</a> <a href="contacts/list">查看嵌套视图</a> <ui-view>点击链接后内容会被加载在这里</ui-view></div>
js
var nest = angular.module(‘nest‘,[‘ui.router‘]);nest.config(function($stateProvider){ $stateProvider.state(‘contacts‘,{ url:‘/contacts‘, templateUrl:‘contacts.html‘ }).state(‘contacts.list‘,{ url:‘/list‘, templateUrl:‘contacts.list.html‘ })});
contacts.html
<h4>联系人列表:</h4><ui-view></ui-view>
contacts.list.html
<p>我是contacts.list的内容</p>
*需要注意的是,子状态的url是以父状态的url为baseUrl的.所以这里子状态的url应该是‘/contacts/list‘
定义状态的‘parent‘属性,属性值是一个字符串:
可以通过状态的parent属性来指定它的父状态.
js:
nest.config(function($stateProvider){ $stateProvider.state(‘contacts‘,{ url:‘/contacts‘, templateUrl:‘contacts.html‘ }).state(‘list‘,{ url:‘/list‘, templateUrl:‘contacts.list.html‘, parent:‘contacts‘ })});
这种方式和上一中方式的区别在于,子状态不需要使用 ‘父状态.子状态‘ 这种格式.但是需要指定子状态的parent属性为‘父状态名‘
基于对象的状态实现嵌套状态:
如果你不喜欢上面说到的两种方式,那么还可以使用基于对象的状态: 为状态添加一个name属性,然后给子状态设置parent属性为父状态对象.
需要注意的是,使用这种方式,子状态的name属性命名规则必须和.state()方法一样,按照‘父状态.子状态‘的格式来命名
var contacts = { name:‘parent‘, //特意不取名叫‘contacts‘ url:‘/contacts‘, templateUrl:‘contacts.html‘};var list = { name:‘parent.child‘, url:‘/list‘, templateUrl:‘contacts.list.html‘, parent:contacts};nest.config(function($locationProvider,$stateProvider){ $stateProvider.state(contacts).state(list);});
状态的注册顺序:
状态的注册顺序无关紧要,你也可以先注册子状态再注册父状态.它会被放在队列里直到父状态被注册的时候才被注册.
父状态必须存在:
如果你只注册了一个子状态,比如contacts.list, 你就必须定义一个叫做contacts的父状态,(定义先后顺序无所谓,但一定要定义),否则的话,将不会有状态被注册.contacts.list这个状态会被放在队列中,直到contacts状态被定义. 如果你不定义父状态,也不会有任何的报错.所以需要注意,为了让子状态生效,必须定义父状态.
状态取名规则:
没有任何两个状态可以拥有相同的名字. 当使用.state()来创建嵌套状态的时候,父状态没有被指定,而是通过推断得到的. 当不使用.state()来创建嵌套状态的时候,parent属性必须被定义,但即使是两个拥有不同父状态的子状态,你依然不能给它们取相同的名字.
状态和视图的嵌套:
当应用处于一个特定的状态时(也就是某个状态被激活时),这个状态的所有祖先状态也都被激活了. 比如上面的所有例子: 当 ‘contacts.list‘ 状态被激活,‘contacts‘ 状态也被隐式的激活了,因为它是 ‘contacts.list‘的父状态.
子状态会把它的视图模板加载到父状态的模板的 ui-view 元素中去.
比如上面的这些例子,只要<a href="http://www.mamicode.com/contacts/list">查看嵌套视图</a>被点击,contacts.list状态被激活,contacts状态也会被隐式的激活.
子状态从父状态继承了什么?
子状态从父状态继承了以下两项:
- 父状态中通过resolve定义的依赖
- 父状态自定义的data属性
其余的,比如控制器,模板,url,等都不会被继承...
resolve继承的栗子:
核心代码:
var contacts = { name:‘parent‘, url:‘/contacts‘, templateUrl:‘contacts.html‘, resolve:{ resA:function(){ return {value:‘A‘} } }, controller:function($scope,resA){ $scope.a = resA.value }};var list = { name:‘parent.child‘, url:‘/list‘, templateUrl:‘contacts.list.html‘, parent:contacts, resolve:{ resB:function(resA){ return {value:resA.value+‘B‘} } }, controller:function($scope,resB){ $scope.b = resB.value }};nest.config(function($locationProvider,$stateProvider){ $locationProvider.html5Mode({enabled:true}).hashPrefix(‘!‘); $stateProvider.state(contacts).state(list);});
contacts.html:
{{a}} //A
contacts.list.html:
{{a}} //A{{b}} //AB
可以看到,contacts.list子状态继承了contacts父状态里resolve的依赖‘resA‘
需要注意: 如果你想在子状态实例化之前解析完父状态的resolve项里的某个promise依赖,那么,这个promise依赖必须被注入到子状态里去.
data继承的栗子:
核心代码:
var contacts = { name:‘parent‘, url:‘/contacts‘, templateUrl:‘contacts.html‘, data:{ dataA:‘a‘, dataB:‘b‘ }, controller:function($scope,$state){ $scope.a = $state.current.data.dataA; }};var list = { name:‘parent.child‘, url:‘/list‘, templateUrl:‘contacts.list.html‘, parent:contacts, controller:function($scope,$state){ $scope.a = $state.current.data.dataA; $scope.b = $state.current.data.dataB; }};nest.config(function($locationProvider,$stateProvider){ $locationProvider.html5Mode({enabled:true}).hashPrefix(‘!‘); $stateProvider.state(contacts).state(list);});
contacts.html:
{{a}} //a
contacts.list.html:
{{a}} //a{{b}} //b
可以看到,父状态的data属性都被子状态继承了
状态的继承是基于视图的继承的
注意,scope作用域的继承和状态的继承无关,它只和视图之间的嵌套关系有关.
很有可能有这种情况: 子状态的视图不仅用于被填充到父状态的视图中,也可能被填充到很多其他地方.在这种情况下.只有被填充到父状态的子状态的视图,才能继承父状态的scope,这种继承只是angular本身的scope继承机制,和状态继承机制是无关的.所以被填充到其他地方的视图是不能访问到父状态的scope的.
angular的uiRouter服务学习(2)