routing with ui-router

原文:https://scotch.io/tutorials/angular-routing-using-ui-router


AngularJS提供了一种非常方便的单页应用程序。当创建单页应用程序时,路由将非常重要。我们希望我们的导航感觉像一个正常的网站,仍然没有我们的网站刷新。我们已经使用常规的ngRoute方法进行了angular 路由。
今天我们将使用UI-Router查看路由。

概述

1.什么是angularUI路由器

UI-Router是由AngularUI团队构建的AngularJS的路由框架。它提供了与ngRoute不同的方法,因为它会根据应用程序的状态(state)更改应用程序视图,而不仅仅是路由URL。

2.states与url路由

使用这种方法,您的视图(view)路由(route)不会被绑定到网站URL。这样,即使URL没有更改,也可以使用路由更改网站的部分。
在使用ngRoute时,您必须使用ngInclude或其他方法,这可能会让人感到困惑。现在,您的所有状态(states)、路由(routing)和视图(views)都在您的. config()中处理,这将在使用您的应用程序的自顶向下视图时提供帮助。


样例应用程序

让我们做一些类似于我们所做的其他路由教程。让我们创建一个home页和一个about页。


开始

让我们开始我们的应用程序,首先需要一些文件

file注释
index.htmlangularJs主页面
home.htmlhome页单页面
about.htmlabout页单页面
module.jsangular代码
homeList.htmlhome页的子页面
homePara.htmlhome页的子页面

index.html(code)

<!DOCTYPE html>
<!--将angular应用程序通过ng-app注入进来-->
<html lang="en" ng-app="app">
<head>
    <meta charset="UTF-8">
    <title>ui-router</title>
    <link rel="stylesheet" href="css/bootstrap.css">

    <script src="js/angular.js"></script>
    <!--注意:先引入angular.js,再引入angular-ui-router.js-->
    <script src="js/angular-ui-router.js"></script>
    <!--最后引入自定义的js文件-->
    <script src="js/module.js"></script>
</head>

<body>
    <nav class="navbar navbar-inverse">
        <ul class="nav navbar-nav">
            <li><a ui-sref="home">Home</a></li>
            <li><a ui-sref="about">About</a></li>
        </ul>
    </nav>

    <div class="container">
        <div ui-view></div>
    </div>

</body>

</html>

注意:

  • ui-router除了加载Angular之外,我们还加载了它。ui-rouer与Angular核心分开,就像ngRoute是分开的。(先加载angular.js再加载angular-ui-router.js)

  • 当使用UI-Router创建链接时,您将使用ui-sref。href将从此生成,您希望将其指向应用程序的某个状态。这些都是在你的app.js。

  • 我们也使用<div ui-view></div>而不是ngRoute的<div ng-view></div>。

我们现在开始我们的Angular应用程序app.js。

app.js(code)

//module.js(尽量不要创建全局变量,污染全局环境)
//将“ui.router”模块依赖注入到主模块中
angular.module("app", ["ui.router"]).
    config(["$stateProvider", "$urlRouterProvider", function ($stateProvider, $urlRouterProvider) {
        $urlRouterProvider.otherwise("/home");
        $stateProvider.
            state("home", {

                url: "/home",
                templateUrl: "tpl/home.html",
            }).
            state("about", {

                url: "/about",
                templateUrl: "tpl/about.html",
            })
    }])

注意:

  • 现在我们已经创建了app的模块,我们已经应用到我们的index.html文件。
  • 在这里我们有一个.state()home和about。在home状态下,我们正在使用模板文件home.html。
  • 我们填写我们的home.html网页,以便我们可以看到信息。

home.html(code)

<div class="jumbotron text-center">
    <h1>The Homey Page</h1>
    <p>This page demonstrates <span class="text-danger">nested</span> views.</p>    
</div>

about.html(code)

<div class="alert alert-danger">
    about page
</div>

……实现图
这里写图片描述

这里写图片描述

嵌套视图 home page

<!--home.html-->
<div class="jumbotron text-center">
    <h1>The Homey Page</h1>
    <p>This page demonstrates <span class="text-danger">nested</span> views.</p>
    <!--嵌套路由-->
    <a ui-sref=".list" class="btn btn-danger">list子页面</a>
    <a ui-sref=".para" class="btn btn-danger">para子页面</a>

    <div ui-view></div>
</div>

注意:

  • 当链接到嵌套视图时,我们将使用点标记:ui-sref=”.list”和ui-sref=”.para”。
  • 这些将在我们的angular中定义,一旦我们设置在那里,我们将注入到我们的新的<div ui-view></div>

    在我们的module.js文件中,我们创建这些嵌套状态。

//module.js(尽量不要创建全局变量,污染全局环境)
//将“ui.router”模块依赖注入到主模块中
angular.module("app", ["ui.router"]).config(["$stateProvider", "$urlRouterProvider", function ($stateProvider, $urlRouterProvider) {
    $urlRouterProvider.otherwise("/home");
    $stateProvider.state("home", {

        url: "/home",
        templateUrl: "tpl/home.html",
    }).state("home.list", {
        url: '/list',
        templateUrl: 'tpl/homeList.html',
        controller: function ($scope) {
            $scope.dogs = ["阿狗", "阿猫", "啊呆"]
        }
    }).state("home.para", {

        url: "/para",
        templateUrl: "tpl/homePara.html",
    }).state("about", {
        url: "/about",
        templateUrl: "tpl/about.html",
    })
}]);

现在我们定义的 home.html与实际状态相关联。随着home.list和home.para创建,这些链接现在将提供模板并注入ui-view。

最后我们需要做的是为home.html定义homeList.html文件。我们也在一个控制器中传递了我们将在模板文件中使用的狗列表。

<!--homeList.html-->
<div>
    <ul>
        <li ng-repeat="dog in dogs">
            dog
        </li>
    </ul>
</div>

…实现图
这里写图片描述
这里写图片描述


绝对路由

如果你使用绝对 url 匹配的方式,那么你需要给你的url字符串加上特殊符号”^”。

$stateProvider
  .state('contacts', {
     url: '/contacts',
     ...
  })
  .state('contacts.list', {
     url: '^/list',
     ...
  });

路由将成为:
‘contacts’状态将匹配”/contacts”
‘contacts.list’状态将匹配”/list”。子状态的url没有附在父状态的url之后的,因为使用了^。


多视图 about page

在应用程序中有多个视图是非常强大的。也许你在你的网站上有一个侧边栏,上面有流行的帖子,最近的帖子,用户,等等。这些都可以被分离出来并注入到我们的模板中。每个人都有自己的控制器和模板文件,这样我们的应用程序就会保持干净。
让我们的应用程序模块化,也可以让我们在不同的模板中重用数据。
对于我们的About页面,让我们创建两个列,并且每个列都有它自己的数据。我们将首先处理视图(about.html),然后看看如何使用ui - router进行此操作。

<!--about.html-->
<div class="alert alert-danger">
    about page
</div>
<div class="row">
    <div class="col-md-6">
        <div ui-view="one"></div>
    </div>
    <div class="col-md-6">
        <div ui-view="two"></div>
    </div>
</div>

这里有多个视图。一个叫one,另一个是two。
为什么有人会使用这种方法呢?这是一个很好的问题。我们是否在创建一个过于模块化的应用程序,这可能会让人感到困惑?从官方的ui - router文档中,这里有一个很好的例子,说明为什么会有多个命名视图。在他们的例子中,他们展示了应用程序的不同部分。每个部分都有它自己的数据,所以每个部分都有自己的控制器(controller)和模板文件(template),使得构建类似这样的东西很容易。

现在,我们的视图已经创建好了,让我们来看看如何将模板文件和控制器应用到每个视图。我们回到我们的module . js。

//module.js(尽量不要创建全局变量,污染全局环境)
//将“ui.router”模块依赖注入到主模块中
angular.module("app", ["ui.router"]).config(["$stateProvider", "$urlRouterProvider", function ($stateProvider, $urlRouterProvider) {
    $urlRouterProvider.otherwise("/home");
    $stateProvider.state("home", {

        url: "/home",
        templateUrl: "tpl/home.html",
    }).state("home.list", {
        url: '/list',
        templateUrl: 'tpl/homeList.html',
        controller: function ($scope) {
            $scope.dogs = ["阿狗", "阿猫", "啊呆"]
        }
    }).state("home.para", {

        url: "/para",
        templateUrl: "tpl/homePara.html",
    }).state("about", {
        url: "/about",
        views: {
            "": {templateUrl: 'tpl/about.html'},
            'one@about': {template: 'i am a column'},
            'two@about': {
                templateUrl: 'tpl/aboutList.html',
                controller: 'controller1'
            }
        }
    });
}]).controller("controller1",["$scope",function($scope){
    $scope.scotches = [
        {
            name: 'Macallan 12',
            price: 50
        },
        {
            name: 'Chivas Regal Royal Salute',
            price: 10000
        },
        {
            name: 'Glenfiddich 1937',
            price: 20000
        }
    ];
}]);
<table class="table">
    <tr>
        <td>name</td>
        <td>cost</td>
    </tr>
    <tr ng-repeat="item in scotches">
        <td>{{item.name}}</td>
        <td>{{item.price}}</td>
    </tr>
</table>

ui -路由器将每个视图分配给一个绝对名称。它的结构是viewName@stateName。由于我们的主要的ui视图在我们的状态,我们给它一个空白的名字。另外两个视图,因为One@about和two @ about。

以这种方式命名方案让我们在一个状态下定义多个视图。这些文档很好地解释了这个概念,我鼓励大家看看他们的例子。非常强大的工具。

..实现图
这里写图片描述


url参数

首先先对$stateParams服务
之前看到的$stateParams服务是一个对象,包含 url 中每个参数的键/值。$stateParams可以为控制器或者服务提供 url 的各个部分。
注意:$stateParams服务必须与一个控制器(controller)相关,并且$stateParams中的“键/值”也必须事先在那个控制器的url属性中有定义


使用$stateParams的两个陷阱

  • 只有当状态被激活并且状态的所有依赖项都被注入时,$stateParams对象才存在。这代表你不能再状态的resolve函数中使用$stateParams对象,可以使用$state.current.params来代替。
$stateProvider.state('contacts.detail', {  
   resolve: { 
      someResolve: function($state){ 
         //*** 不能在这里使用 $stateParams , the service is not ready ***//
         //*** 使用 $state.current.params 来代替 ***//
         return $state.current.params.contactId + "!" 
      }; 
   },
   // ...
})
  • 在状态控制器中,$stateParams对象只包含那些在状态中定义的参数,因此你不能访问在其他状态或者祖先状态中定义的参数。
$stateProvider.state('contacts.detail', {
   url: '/contacts/:contactId',   
   controller: function($stateParams){
      $stateParams.contactId  //*** Exists! ***//
   }
}).state('contacts.detail.subitem', {
   url: '/item/:itemId', 
   controller: function($stateParams){
      $stateParams.contactId //*** 注意! DOESN'T EXIST!! ***//
      $stateParams.itemId //*** Exists! ***//  
   }
})

// 如果状态中 url 属性是:
url: '/users/:id/details/{type}/{repeat:[0-9]+}?from&to'

// 当浏览
'/users/123/details//0'

// $stateParams 对象将是
{ id:'123', type:'', repeat:'0' }

// 当浏览
'/users/123/details/default/0?from=there&to=here'

// $stateParams 对象将是
{ id:'123', type:'default', repeat:'0', from:'there', to:'here' }

1.基本参数(:value)

$stateProvider.
    $state("contacts.detail",{
    //这里设置url参数
    url:'/contacts/:contactId',
    templateUrl:'contacts.detail.html',
    controller:function($stateParams){
    //获取参数传来的值
    id = $stateparams.contactId;
    }
    })

特例:含正则表达式的参数

2.查询参数(?value)
可以指定?来制定参数作为查询参数

url:'/contacts?myParams&add'
//匹配'/contacts?myParams=value&add=value2'

1)
2)使用参数而不用在状态url中指定它们
即使参数没有出现在url中,您仍然可以指定要接收的参数。您需要在状态中添加一个新的字段params,并根据链接中使用参数指定的链接创建链接
例如,你有状态。


$urlRouterProvider

$urlRouterProvider负责处理在状态配置中指定的url路由方式之外的 url 请求的路由方式。
$urlRouterProvider负责监视$location,当$location改变后,$urlRouterProvider将从一个列表,一个接一个查找匹配项,直到找到。所有 url 都编译成一个UrlMatcher对象。
$urlRouterProvider有一些实用的方法,可以在module.config中直接使用。

  • when() for redirection 重定向
    参数:
    what - String | RegExp | UrlMatcher,你想重定向的传入路径
    handler - String | Function 将要重定向到的路径

    1)handler 作为 String(如果handler是字符串,它被视为一个重定向,并且根据匹配语法决定重定向的地址。)
    2)handler 作为 Function
    如果handler是一个函数,这个函数是注入一些服务的。如果$location匹配成功,函数将被调用。你可以选择性注入$match
    falsy 表明规则不匹配,$urlRouter将试图寻找另一个匹配
    String 该字符串作为重定向地址并且作为参数传递给$location.url()
    nothing或者任何为真的值,告诉$urlRouterurl 已经被处理

1)
app.config(function($urlRouterProvider){
    // when there is an empty route, redirect to /index   
    $urlRouterProvider.when('', '/index');

    // You can also use regex for the match parameter
    $urlRouterProvider.when('/aspx/i', '/index');
})

-

2)handler 作为 Function
如果handler是一个函数,这个函数是注入一些服务的。如果 location match。
函数可以返回:
falsy - 表明规则不匹配, urlRouterString location.url()
nothing或者任何为真的值,告诉$urlRouterurl 已经被处理

结论

这是一个关于ui -路由器的伟大工具的概述。您可以使用它来做的事情是不可思议的,当您将应用程序看作状态而不是ngRoute选项时,可以轻松地创建具有模块化和可扩展的角应用程序。

相关ui-router:http://ngmodules.org/modules/ui-router#get-started

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值