-
$state / $stateProvider:管理状态定义、当前状态和状态转换。包含触发状态转换的事件和回调函数,异步解决目标状态的任何依赖项,更新
$location
到当前状态。由于状态包含关联的 url,通过$urlRouterProvider生成一个路由规则来执行转换的状态。 -
ui-view指示器:渲染状态中定义的视图,是状态中定义的视图的一个占位符。
-
$urlRouter / $urlRouterProvider:管理了一套路由规则列表来处理当
$location
发生变化时如何跳转。最低级的方式是,规则可以是任意函数,来检查$location
,并在处理完成时候返回true
。支持正则表达式规则和通过$urlMatcherFactory
编译的UrlMatcher
对象的 url 占位符规则。 -
$urlMatcherFactory:将 url和占位符编译为
UrlMatcher
对象。除了$routeProvider
支持的占位符语法之外,它还支持扩展语法,允许一个正则表达式指定占位符,并且能够提取命名参数和查询url的一部分。 -
$templateFactory - 通过
$http
/$templateCache
来加载模板,供状态配置中使用。
AngularJS不需要任何第三方库,利用自身集成的各个模块便可开发出功能齐全的web应用,不过活跃的AngularJS社区也开发了很多能够最大限度强化web应用的编程库。本文带读者了解专业开发使用的模块AngularUI中的ui-路由(ui-router)。AngularUI库已经被分成了几个模块,用户可以只选择载入自己感兴趣的模块,而不用载入整个库。
UI-Router
UI-Router被认为是AngularUI为开发者提供的最实用的一个模块,它是一个让开发者能够根据URL状态或者说是'机器状态'来组织和控制界面UI的渲染,而不是仅仅只改变路由(传统AngularJS应用实用的方式)。该模块为开发者提供了很多最视图(view)额外的控制。开发者可以创建嵌套分层的视图、在同一个页面使用多个视图、让多个视图控制某个视图等更多的功能。即使是非常复杂的web应用,UI-Router也可以极佳地驾驭。
安装
安装方式可以选择下载发行版本或者使用Bower(前端包管理器):
$ bower install angular-ui-router --save
同时也需要将源文件包含到页面中:
>
接下来,将UI-Router作为web应用的依赖,注入到主程序:
angular.module('myApp', ['ui.router']);
与集成的ngRoute服务不同的是,UI-Router可以将视图嵌套,因为它基于的是操作状态而仅非URL。与传统做法使用ng-view不同的是,在ngRoute里需要使用ui-view服务。当在ui-router中处理路由和状态时,开发者的重心是当前的状态是什么以及在哪一个页面里。
ng-controller="DemoController"> ui-view>> >
和ngRoute一样,为特定状态指定的模板将会放在元素中。在这些模板中也可以包含自己的
ui-view
,这就是在同一个路由下实现嵌套视图的方法。要定义一个路由,与传统的方法相同:使用.config
方式,但使用的不是$routeProvider
而是$stateProvider
。
.config(function($stateProvider, $urlRouterProvider) { $stateProvider .state('start', { url: '/start', templateUrl: 'partials/start.html' }) });
上述代码在设置对象上定义了一个叫start
的状态。设置对象stateConfig
和路由设置对象的选项是非常相似的。
模板,模板路径,模板Provider
开发者可以在每个视图下使用如下方式来设置模板 - template - HTML字符串,或者是返回HTML字符串的函数 - templateUrl - HTML模板的路径,或者是返回HTML模板路径的函数 - templateProvider - 返回HTML字符串的函数 例如:
$stateProvider.state('home', { template: 'Hello {{ name }}
' });
控制器
和ngRoute
相似,开发者可以指定任何已经被注册的控制器,或者在路由里面创建一个作为控制器的函数。但如果没有定义模板,控制器将无效。
预载入Resolve
使用预载入功能,开发者可以预先载入一系列依赖或者数据,然后注入到控制器中。在ngRoute
中resolve
选项可以允许开发者在路由到达前载入数据保证(promises)。在使用这个选项时比使用angular-route有更大的自由度。
预载入选项需要一个对象,这个对象的key即要注入到控制器的依赖,这个对象的value为需要被载入的factory
服务。
如果传入的时字符串,angular-route会试图匹配已经注册的服务。如果传入的是函数,该函数将会被注入,并且该函数返回的值便是控制器的依赖之一。如果该函数返回一个数据保证(promise),这个数据保证将在控制器被实例化前被预先载入并且数据会被注入到控制器中。
$stateProvider.state('home', { resolve: { //这个函数的值会被直接返回,因为它不是数据保证 person: function() { return { name: "Ari", email: "ari@fullstack.io" } }, //这个函数为数据保证, 因此它将在控制器被实例化之前载入。 currentDetails: function($http) { return $http({ method: 'JSONP', url: '/current_details' }); }, //前一个数据保证也可作为依赖注入到其他数据保证中!(这个非常实用) facebookId: function($http, currentDetails) { $http({ method: 'GET', url: 'http://facebook.com/api/current_user', params: { email: currentDetails.data.emails[0] } }) } }, //定义控制器 controller: function($scope, person, currentDetails, facebookId) { $scope.person = person; } })
URL
url选项将会为该应用的状态指定一个URL基于用户浏览该应用所在的状态。这样当在浏览该应用的时候便能实现深度链接
的效果。 该选项与ngRoute的URL相似,但可以被视为对ngRoute主要的升级,在接下来的文章里你便会认可这一点。开发者可以这样指定一个基本的路由。
$stateProvider
.state('inbox', { url: '/inbox', template: 'Welcome to your inbox
' });
当用户浏览到/inbox
时,该应用将状态改为inbox
同时向主ui-view元素中插入模板中的内容('Welcome to your inbox')。URL参数有多个选项,因此它非常强大。开发者可以像设置ngRoute一样设置最基本的参数:
$stateProvider
.state('inbox', { url: '/inbox/:inboxId', template: 'Welcome to your inbox
', controller: function($scope, $stateParams) { $scope.inboxId = $stateParams.inboxId; } });
现在将:inboxId
最为URL的第二个部分,例如:访问/inbox/1,那么$stateParams.inboxId
就为1($stateParams为{inboxId:1})。同时也可使用不同的语法:
url: '/inbox/{inboxId}'
路径必须匹配URL,与ngRoute不同的是,当用户访问到/inbox/
时,上面的的路径会被激活,然而当访问到/inbox
时不会被激活。路径同时也使开发者可以使用正则表达式来匹配,例如:
// 限定id为6位16进制数字
url: '/inbox/{inboxId:[0-9a-fA-F]{6}}', // 或者 // 匹配任何在 `/inbox`后面的url(慎用)并匹配值到indexId url: '/inbox/{inboxId:.*}'
注意,在路由中目前还无法使用路由组,路由数据预载入器无法预载入。
在路径里也可以指定查询参数:
// /inbox?sort=ascending 将会被匹配
url: '/inbox?sort'
嵌套路由
使用url参数可以实现嵌套的路由,有了嵌套路由便可在同一个模板同一个路由实现多层次的ui-view,例如在/inbox中嵌入更多路由:
$stateProvider
.state('inbox', { url: '/inbox/:inboxId', template: '