在单页面应用中要把各个分散的视图给组织起来是通过路由机制来实现的。本文主要对 AngularJS 原生的 ngRoute 路由模块和第三方路由模块 ui.router 的用法进行简单介绍,并做一个对比。
1) 引入 angular-route lib
无论是 ngRoute 还是 ui.router ,作为框架额外的附加功能,都必须以 模块依赖 的形式被引入。
1
|
<script src="lib/angular-route.js"></script>
|
2) 配置路由
1
|
var app = angular.module(‘ngRouteApp‘, [‘ngRoute‘]);
|
ngRoute 路由模块名
$routeProvider 服务提供者,用来定义一个路由表,即地址栏与视图模板的映射,对应于ui.router 中的 urlRouterProvider 和 stateProvider
$route 服务,完成路由匹配,并且提供路由相关的属性访问及事件,如访问当前路由对应的 Controller,对应于下面的 $urlRouter 和 $state$routeParams 服务,保存了地址栏中的参数,对应于下面的 $stateParams
ng-view 指令,用来在主视图中指定加载子视图的区域,对应于下面的 ui-view
1) 引入 angular-ui-router lib
1
|
<script src="lib/angular-ui-router.min.js"></script>
|
2) 配置路由
1
|
var app = angular.module("uiRouteApp", ["ui.router"]);
|
ui.router 路由模块名
$urlRouterProvider 服务提供者,用来配置路由重定向$stateProvider 服务提供者,用来配置路由
$urlRouter 服务$state 服务,用来显示当前路由状态信息,以及一些路由方法(如:跳转)$stateParams 服务,用来存储路由匹配时的参数
ui-view 指令,路由模板渲染,对应的 dom 相关联ui-sref 指令,链接到特定状态
调用 $stateProvider.state(...) 方法,并可配置以下参数
1
|
$stateProvider
|
有两种方式可以指定父子状态关系。
一种是,使用点标记法,像本文最后嵌套视图部分举得栗子那样:
1
|
.state("tabs.tab1", {})
|
另一种是,使用 parent 属性
1
|
.state("tab1", {
|
使用 abstract 可以为所有的子状态提供一个基 URL,这样做的好处就是可以在抽象出来的这个状态所对应的 html 页面中来定义静态资源。抽象模板不能被激活。
1
|
$stateProvider
|
resolve 在 state 配置参数中,是一个对象(key-value),每一个 value 都是一个可以依赖注入的函数,并且返回的是一个 promise (当然也可以是值)。
1
|
resolve: {
|
这样做的目的:
controller 的操作,将数据的获取放在 resolve 中进行,这在多个视图多个controller 需要相同数据时,有一定的作用。reslove 中的 promise 全部 resolved(即数据获取成功)后,才会触发$stateChangeSuccess 切换路由,进而实例化 controller,然后更新模板。更多参数可参考 angular 系列八 ui-router详细介绍及ngRoute工具区别 中 state 参数的讲解。
url 动态部分被称为参数,有以下几种方式设置
1) 使用花括号的方式可以设置一个正则表达式规则的参数:
1
|
//只会匹配 pageId 为1到8位的数字
|
可以通过 ? 来指定参数作为查询参数
1
|
//比如匹配 href="/page?type=‘new‘"
|
如果需要不止一个查询参数,用 & 分隔:
1
|
//比如匹配 ui-sref="page({type:‘all‘, title:‘test ui-router‘})"
|
angular 在刚开始的 $digest 时,$rootScope 会触发 $locationChangeSuccess 事件(angular 在每次浏览器 hash change 的时候也会触发 $locationChangeSuccess 事件)ui.router 监听了 $locationChangeSuccess 事件,于是开始通过遍历一系列 rules,进行路由查找匹配列表项$state.transitionTo(state,...),跳转激活对应的 state在视图中,建议使用 ui-sref="xxxState" 而不是 href="#/abc",这样做能减少一遍 rules循环的遍历,提升性能。
ngRoute模块 是 Angular 自带的路由模块,而 ui.router模块 是基于 ngRoute模块 开发的第三方模块。
ui.router 是基于 state(状态)的, ngRoute 是基于 url 的,ui.router模块 具有更强大的功能,主要体现在视图的嵌套方面。
页面某个动态变化区块中,嵌套着另一个可以动态变化的区块。
前面的栗子就是一个很好的业务场景。
在首页中包含一个动态区块:
1
|
<body ng-app="ngRouteApp">
|
在标签页中又包含动态区块:
1
|
<div>
|
一运行,报了一个这样的错误:
RangeError: Maximum call stack size exceeded
发现浏览器崩溃了,因为 ng-view 会陷入死循环,无限递归下去。
使用 ui.router 能很容易解决这个问题,因为它定义的路由有明确的父子关系,并通过 ui-view 指令将子路由模版插入到父路由模板的 <div ui-view></div> 中去,从而实现视图嵌套。看代码:
1
|
$stateProvider
|
ui-router(左) : ngRoute(右)
原文:http://www.cnblogs.com/ilinuxer/p/5244108.html