zoukankan      html  css  js  c++  java
  • angular的uiRouter服务学习(4)

    本篇接着上一篇angular的uiRouter服务学习(3)继续讲解uiRouter的用法

    本篇主要讲解uiRouter的url路由

    大多数情况下,状态是和url相关联的: 当url改变,激活对应的状态.当状态发生改变,同步url. 所以,在设置状态的一开始,就应该把url路由的设计考虑进去,同时保持路由和状态的分离.

    其实在之前几篇的栗子里,已经多次用到了url路由,比如:

    $stateProvider
        .state('contacts', {
            url: "/contacts",
            templateUrl: 'contacts.html'
    })

    当url被导航到baseUrl/contacts,contacts状态就会被激活,然后ui-view元素就会被contacts.html填充.另外,如果我们使用transitionTo('contacts')来激活contacts状态,url也会被更新为 baseUrl/contacts

    URL 参数

    基本参数

    通常,url会有动态的部分,这些部分就是url参数.有几种方法可以定义url参数.下面是一个最基本的栗子:

    $stateProvider.state('contacts.detail', {
            url: "/contacts/:contactId",
            templateUrl: 'contacts.detail.html',
            controller: function ($stateParams) {
                $scope.contactId = $stateParams.contactId;  
            }
    })

    也可以使用花括号:

    url: "/contacts/{contactId}" 

    下面举几个常用的栗子: 

      <p>
        hello/路由:<a href="hello/">'hello/'</a>
      </p>
    
      <p>
        hello/1路由: 匹配'/hello/'无效 <a href="hello/1">'hello/1 无效'</a>
      </p>
    
      <p>
        hello路由: 匹配'/hello/'无效 <a href="hello">'hello 无效'</a>
      </p>
    
      <p>
        user/1路由: 匹配'user/{id}'或'user/:id' <a href="user/1">'user/:id'</a>
      </p>
    
      <p>
        user/1/路由: 匹配'user/:id'无效 <a href="user/1/">'user/:id/ 无效'</a>
      </p>
    
      <p>
        user/路由:  <a href="user/">'user/'</a>
      </p>
    
      <p>
        user/anotheruser路由: 匹配'user/{id:int}'无效 <a href="user/anotheruser">'user/{id:int} 下无效'</a>
      </p>
    var hello = {
        name:'hello',
        /*注意,只能匹配到'/hello/',最后一个/不能少,最后一个/后面也不能再有其他内容*/
        url:'/hello/',
        template:'<h3>/hello/</h3>'
    };
    var user = {
        name:'user',
        /*注意,可以匹配到/user/,也就是说,参数为空也能被匹配到,使用花括号和使用:完全一致*/
        /*url:'/user/:id',*/
        /*url:'/user/{id}',*/
        /*使用了:int,user/后面必须是一个整数,否则不匹配*/
        url:'/user/{id:int}',
        templateProvider: function($stateParams){
            return '<h1>user/'+$stateParams.id+'</h1>'
        }
    };

    '/hello/': 只能匹配到'/hello/',最后一个/不能少,最后一个/后面也不能再有其他内容, 'hello/1'无效, 'hello'也无效

    '/user/:id' 或 'user/{id}': 两种写法效果一样. 可以匹配 'user/', 可以匹配'user/...', 不能匹配'user/.../' user后面内容会被作为$stateParams的id属性值

    '/user/{id:int}': id必须为整数. 不能匹配到'user/anotheruser'这样id不是整数的url

    正则参数

    使用花括号来定义参数,可以自定义正则来匹配url: 

    var user = {
        name:'user',
        /*id的长度在1-8位之间*/
        url:'/user/{id:[0-9a-fA-F]{1,8}}',
        templateProvider: function($stateParams){
            return '<h1>user/'+$stateParams.id+'</h1>'
        }
    };

    下面举几个正则的栗子:

    <p>
        contacts/0123456789路由: 匹配'contacts/{contactId:[0-9]{1-8}}'无效
        <a href="contacts/0123456789">'contacts/{contactId:[0-9]{1-8}}'</a>
    </p>
    var user = {
        name:'user',
        /*相当于{id}*/
        /*url:'/user/{id:[^/]*}',*/
        /*id的长度在1-8位之间*/
        url:'/user/{id:[0-9a-fA-F]{1,8}}',
        templateProvider: function($stateParams){
            return '<h1>user/'+$stateParams.id+'</h1>'
        }
    };
    var contacts = {
        name:'contacts',
        /*匹配0-9数字,长度在1-8之间*/
        url:'/contacts/{contactId:[0-9]{1,8}}',
        templateProvider:function($stateParams){
            return '<h1>contacts/'+$stateParams.contactId+$stateParams.myParam+$stateParams.myName+'</h1>'
        }
    };

    '/user/{id:[^/]*}': 相当于'/user/:id''/user/{id}'

    'contacts/{contactId:[0-9]{1-8}}': contactsId是长度为1-8位的数字, 比如上面超过8位的url 'contacts/0123456789' ,就不会被匹配到.

    '/user/{id:[0-9a-fA-F]{1,8}}': id是长度为1-8的任意字符.

    匹配包含'/'的全部内容作为参数:

    前面说到的匹配路径,都是把 / 后面的内容捕获为参数的,但如果 / 后面还有 /,那么不仅不会被捕获,而且url不会被匹配到.如果需要捕获 / 后面的全部内容作为参数,可以这样写:

    <p>
        files/paths/path路由: files后面整体作为一个参数<a href="files/paths/path">'/files/*path'</a>
    </p>
    var files = {
        name:'files',
        /*匹配/files/开头的所有url,后面有多少个'/'都可以,'/'部分也会被作为path这个整体*/
        /*url:'/files/{path:.*}',*/
        /*同上,获取包括'/'的全部作为参数的一种简写*/
        url:'/files/*path',
        templateProvider:function($stateParams){
            return '<h1>files/'+$stateParams.path+'</h1>'
        }
    };

    url参数的参数:

    还可以把url的参数也可以被作为参数捕获到$stateParams里.

      <p>
        contacts/0123?myParam路由:
        <a href="contacts/0123?myParam">'/contacts/{contactId:[0-9]{1-8}}?myParam'</a>
      </p>
      <p>
        contacts/0123?myParam=param&myName=name路由: <a href="contacts/0123?myParam=param&myName=name">'/contacts/{contactId:[0-9]{1-8}}?myParam&myName'</a>
      </p>
    var contacts = {
        name:'contacts',
        /*匹配0-9数字,长度在1-8之间*/
        /*url:'/contacts/{contactId:[0-9]{1,8}}',*/
        /*在上面的基础上,必须要有myParam参数*/
        /*url:'/contacts/{contactId:[0-9]{1,8}}?myParam',*/
        /*在上面的基础上,必须要有myParam和myName两个参数*/
        url:'/contacts/{contactId:[0-9]{1,8}}?myParam&myName',
        templateProvider:function($stateParams){
            return '<h1>contacts/'+$stateParams.contactId+$stateParams.myParam+$stateParams.myName+'</h1>'
        }
    };

    在url后面加上?myParam,则url的myParam参数值会被捕获,成为$stateParams的myParam属性值.

    注意,即使url不带有myParam参数,它一样可以被匹配,$stateParams的myParam属性值就是undefined.

    如果要捕获多个参数,可以用 & 符号连接多个参数

    嵌套状态的url路由:

    追加url(默认方式):

    嵌套状态路由匹配时,子状态的url前会加上父状态的url,然后匹配和在一起的那个url:

      <p>
        contacts/0123?myParam=param&myName=name路由: <a href="contacts/0123?myParam=param&myName=name">'/contacts/{contactId:[0-9]{1-8}}?myParam&myName'</a>
      </p>
    
      <p>
        contacts/list/0123?myParam路由: '/contacts'路由的子路由'/list': <a href="contacts/list/0123?myParam">'/contacts/list'</a>
      </p>
    
      <p>
        list/0123?myParam路由: '/contacts'路由的子路由'^/list'<a href="list/0123?myParam">'/list'</a>
      </p>
    var contacts = {
        name:'contacts',
        url:'/contacts',
        template:'<div ui-view></div>'
    };
    var list = {
        name:'contacts.list',
        url:'/list/{contactId:[0-9]{1,8}}?myParam',
        parent:'contacts',
        templateProvider:function($stateParams){
            return '<h1>contacts/'+$stateParams.contactId+$stateParams.myParam+$stateParams.myName+'</h1>'
        }
    };

    list是contacts的子状态,所以list状态匹配的url应该是父状态的url+子状态的url: '/contacts/list/{contactId:[0-9]{1,8}}?myParam'

    绝对url:

    在子状态的url前加上 ^ 符号,则子状态的url前不会拼合父状态的url:

    同样上面的这个栗子:

    url:'^/list/{contactId:[0-9]{1,8}}?myParam'

    则子状态匹配的url就是'/list/{contactId:[0-9]{1,8}}?myParam' 

    $stateParams 服务:

    关于$stateParams这个服务,之前的栗子里已经用到过很多次了. 可以知道,它是一个对象,用于存放url里的参数,这里的参数有两种,一种是状态的url属性里定义的参数,另外一个就是url?后面的参数.无论哪一种,每一个参数都会被放在$stateParams对象里.使用$stateParams可以让我们使用url中的任意部分.

    注意: $stateParams服务只能用在状态里.不能注入到其它地方. 

    下面来看一个$stateParams的栗子:

      <p>
        users/123/detail//0路由: <a href="users/123/details//0">'/users/:id/details/{type}/{repeat:[0-9]+}?from&to'</a>
      </p>
    
      <p>
        users/123/detail/default/0?from=there&to=here路由: <a href="users/123/details/default/0?from=there&to=here">'/users/:id/details/{type}/{repeat:[0-9]+}?from&to'</a>
      </p>
    var users = {
        name:'users',
        url:'/users/:id/details/{type}/{repeat:[0-9]+}?from&to',
        templateProvider:function($stateParams){
            console.log($stateParams);
            return '<h1>'+$stateParams.type+' '+$stateParams.repeat+' '+$stateParams.from+' '+$stateParams.to+'</h1>'
        }
    };

    这里url里一共定义了5个参数: id  type  repeat  from  to

    当导航到匹配的路径时,状态被激活,栗子中的两个url所对应的$stateParams如下:

    $stateParams 服务的两个陷阱:

    *以下两个问题只存在于老的版本中,最新版本的测试发现,这两个问题都已经没有了.

    1.每个状态所对应的$stateParams只包含该状态url里定义的参数,不包含其它状态里定义的参数,即使是父状态,子状态,也不包含.

    2.$stateParams和$routeParams一样,是等到状态被激活完成,resolve都解析后才生成的,所以是不能用在resolve函数里的,只能用$state.current.params来替代.

    但是新版本的已经解决了这个问题.现在可以在resolve函数里使用了.

      

    $urlRouterProvider

    $urlRouterProvider服务用来监测$location. 当$location发生变化时,它会根据你定义的规则一一匹配,直到找到所匹配的. 所有的url都会被编译到一个urlMatcher对象里(详情查看下面的$urlMatcherFactory) 

    $urlRouterProvider有下面几个方法.可以使用这些方法在模型中进行配置:

    app.config(function($urlRouterProvider){    
        $urlRouterProvider.when().otherwise().rule()
    });

    .when(what,handler) 方法重定向url:

    what: 字符串/正则/urlMatcher对象,表示需要重定向的url

    handler: 字符串/函数, 表示要重定向到的url

    如果handler是一个字符串,它就是要重定向到的地址.

    handler是字符串的栗子:

      <p><a href="/">''</a>
      </p>
    urlRouting.config(function($urlRouterProvider){
        $urlRouterProvider.when('/','/hello/')
    });

    当点击这个空链接的时候,他会重定向到/hello/,激活对应的状态.

    如果handler是函数,那么它可以被注入服务.可以注入$match服务: (这一部分没有搞懂)

    .otherwise() 方法重定向url:

    传入一个参数,字符串或者函数, 字符串表示你想要重定向到的url地址. 函数返回想要重定向到的地址. 函数可以被注入两个依赖: $injector$location

    urlRouting.config(function($urlRouterProvider){
        /*没有匹配到任何状态或者.when()重定向时,重定向到'users/123/details//0'*/
        $urlRouterProvider.otherwise('users/123/details//0')
    });

    打开页面直接重定向到 'users/123/details//0'

    .rule() 方法自定义url处理方式:

    .rule()方法接受一个函数作为参数,函数可以注入$injector和$location服务.返回一个字符串格式的有效路由.

    举个栗子:

      <p>
        HELLO/ <a href="HELLO/">'HELLO/'</a>
      </p>
        $urlRouterProvider.rule(function($injector,$location){
            var path = $location.path(),normalized = path.toLowerCase();
            if(path!==normalized){
                return normalized
            }
        })

    通过rule函数,HELLO/会被转换成hello/,激活对应的状态

     

    $urlMatcherFactory和urlMatchers

    在前面介绍$urlRouterProvider的.when()方法时,说到.when()的第一个参数what格式可以是字符串,函数,urlMatcher对象.那么什么是urlMatcher对象呢,也就是通过$urlMatcherFactory定义的url规则.

    使用$urlMatcherFactory.compile('path')传入一个路由规则.path的定义规则和定义状态时的url定义的规则是一致的:

    如果要使用$urlMatcherFactory,需要链入ui.router.util依赖.如果不引入依赖,可以使用ui.router自带的$urlMatcherFactoryProvider

    看如下栗子:

    urlRouting.config(function($locationProvider,$stateProvider,$urlRouterProvider,$urlMatcherFactoryProvider){    var urlMatcher = $urlMatcherFactoryProvider.compile('/home/:id?param1');
        $stateProvider.state('mystate',{
            url:urlMatcher,
            templateProvider:function($stateParams){
                return '<h1>mystate'+ $stateParams.id +'</h1>'
            }
        });
        /*注意如果一个urlMatcher既匹配了状态里的url,又匹配了.when,以状态为准,不会重定向*/
        $urlRouterProvider.when(urlMatcher,'hello/');
    });

    可以看到,.compile里传入了一个路由规则,这个规则可以直接作为状态的url属性值.也可以作为$urlRouterProvider.when()的第一个参数.

    参考原文: https://github.com/angular-ui/ui-router/wiki/URL-Routing 

  • 相关阅读:
    游标cursor
    SQL: EXISTS
    LeetCode Reverse Integer
    LeetCode Same Tree
    LeetCode Maximum Depth of Binary Tree
    LeetCode 3Sum Closest
    LeetCode Linked List Cycle
    LeetCode Best Time to Buy and Sell Stock II
    LeetCode Balanced Binary Tree
    LeetCode Validate Binary Search Tree
  • 原文地址:https://www.cnblogs.com/liulangmao/p/4200600.html
Copyright © 2011-2022 走看看