zoukankan      html  css  js  c++  java
  • 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="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的. 

    抽象状态

    一个抽象状态它拥有自己的子状态,但是它不能激活自己. 它只能当子状态被激活的时候,隐式的被激活.

    如果要让一个状态成为抽象状态,需要给它设置abstract属性为true

    下面是几种抽象状态常用的场合:

    • 给子状态们的url提供一个基础url.
    • 插入带有ui-view(s)的视图模板,显示子状态们通用的内容,而ui-view部分供各个子状态不同的视图模板来填充.
      • 可以给视图添加一个控制器
      • 另外,这样也可以把$scope对象继承给子状态.但是注意,就如同上一点所说的,这是通过angular的scope的视图继承机制实现的,不是状态继承    
    • 通过data属性,给子状态们提供数据.
    • 通过resolve属性,给子状态们提供依赖.
    • 通过触发onEnter和onExit回调,来处理一些事情.
    • 以上几种情况的混合.

    注意: 抽象状态也需要带有<ui-view>元素来让子状态视图填充,所以,如果你创建抽象状态是为了给子状态提供基础url,提供resolve依赖,data数据,或者调用onEnter和onExit回调,那么你需要在template属性中设置视图模板为:''<ui-view/>". 

    下面简单举几个栗子:

    栗子1:给子状态们的url提供一个基础url.

    html:

    <div>
      <a href="contacts">查看视图</a>
      <a href="contacts/list">查看嵌套视图1</a>
      <a href="contacts/detail">查看嵌套视图2</a>
      <ui-view>点击链接后内容会被加载在这里</ui-view>
    </div>

    js:

    var contacts = {
        abstract:true,
        name:'parent',
        url:'/contacts',
        template:'<ui-view/>'
    };
    var list = {
        name:'parent.child',
        url:'/list',
        templateUrl:'contacts.list.html',
        parent:contacts
    };
    var detail = {
        name:'parent.detail',
        url:'/detail',
        templateUrl:'contacts.detail.html',
        parent:contacts
    };
    nest.config(function($locationProvider,$stateProvider){
        $locationProvider.html5Mode({enabled:true}).hashPrefix('!');
        $stateProvider.state(contacts).state(list).state(detail);
    });

    contacts.list.html:

    <p>我是contacts.detail</p>

    contacts.detail.html:

    <p>我是contacts.detail</p>

    当url变为'contacts/list'和'contacts/detail'的时候,会激活相应的状态

    ------------------------------------------------------------------------------------------------------------------------------------------

    栗子2: 父状态插入带有ui-view(s)的视图模板,显示子状态们通用的内容,而ui-view部分供各个子状态不同的视图模板来填充.

    html同上.

    js:

    var contacts = {
        abstract:true,
        name:'parent',
        url:'/contacts',
        templateUrl:'contacts.html'
    };
    var list = {
        name:'parent.child',
        url:'/list',
        templateUrl:'contacts.list.html',
        parent:contacts
    };
    var detail = {
        name:'parent.detail',
        url:'/detail',
        templateUrl:'contacts.detail.html',
        parent:contacts
    };
    nest.config(function($locationProvider,$stateProvider){
        $locationProvider.html5Mode({enabled:true}).hashPrefix('!');
        $stateProvider.state(contacts).state(list).state(detail);
    });

    contacts.html:

    <h4>联系人列表:</h4>
    <ui-view></ui-view>

    无论切换哪个子状态,contacts.html中的<h4>联系人列表:</h4>部分都是通用的.

    ------------------------------------------------------------------------------------------------------------------------------------------

    栗子3: 混合使用

    html:

    <div>
      <a href="contacts">查看视图</a>
      <a href="contacts/list">查看嵌套视图1</a>
      <ui-view>点击链接后内容会被加载在这里</ui-view>
    </div>

    js:

    var contacts = {
        abstract:true,
        name:'parent',
        url:'/contacts',
        templateUrl:'contacts.html',
        controller:function($scope){
            $scope.contacts = [{id:0,name:'code_bunny'},{id:1,name:'white_bunny'},{id:2,name:'black_bunny'}]
        }
    };
    var list = {
        name:'parent.child',
        url:'/list',
        templateUrl:'contacts.list.html',
        parent:contacts
    };
    var detail = {
        name:'parent.detail',
        url:'/detail/:id',
        templateUrl:'contacts.detail.html',
        parent:contacts,
        controller:function($scope,$stateParams){
            $scope.id = $stateParams.id
        }
    };
    nest.config(function($locationProvider,$stateProvider){
        $locationProvider.html5Mode({enabled:true}).hashPrefix('!');
        $stateProvider.state(contacts).state(list).state(detail);
    });

    contacts.html:

    <h4>联系人列表:</h4>
    <ui-view></ui-view>

    contacts.list.html:

    <ul>
      <li ng-repeat="contact in contacts">
        <a href="contacts/detail/{{contact.id}}">{{contact.name}}</a>
      </li>
    </ul>

    contacts.detail.html:

    <p>{{contacts[id]['name']}}</p>

    完整代码: https://github.com/OOP-Code-Bunny/angular/tree/master/uiRouter

    参考网站: https://github.com/angular-ui/ui-router/wiki/Nested-States-%26-Nested-Views

  • 相关阅读:
    mysql5.7 ERROR 1045 (28000): Access denied for user解决方法
    C++ json解决方案
    Gitblit无法查看单个文件解决方案
    git 拉取指定的远程分支(三种方式)
    全栈12
    git commit之后,想撤销commit
    video
    iframe
    git恢复之前版本的两种方法reset、revert
    Eclipse
  • 原文地址:https://www.cnblogs.com/liulangmao/p/4167394.html
Copyright © 2011-2022 走看看