为什么需要前端路由
Ajax
请求不会留下history
记录
- 用户无法直接通过 url 进入应用中的指定页面(保存书签,链接分享给朋友)
Ajax
对SEO
不友好(没法让搜索引擎索引)
Angular 路由
在APP
中定义多个页面的控制器,并给出对应的模板。然后$routeProvider
进行配置,即可将 URL 映射到这些控制器和视图。 首先定义一个基本的 Angular APP,并引入ngRoute
:
Angular$routeService
在ngRoute
模块里。需要引入它对应的 JavaScript 文件,并在我们的 APP 里ngRoute
添加为模块依赖。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| var app = angular .module('ngRouteExample', ['ngRoute']) .controller('MainController', function($scope) {}) .config(function($routeProvider, $locationProvider) { $routeProvider .when('/users', { templateUrl: 'user-list.html', controller: 'UserListCtrl' }) .when('/users/:username', { templateUrl: 'user.html', controller: 'UserCtrl' }) .otherwise({ redirectTo: '/hello' })
$locationProvider.html5Mode(true) })
|
上述代码中,$routeProvider
定义了两个 URL 的映射:/users
使用user-list.html
作为模板,UserListCtrl
作为控制器;/users/:username
则会匹配类似/users/alice
之类的 URL,稍后你会看到如何获得:username
匹配到的值。先看首页的模板:
HTML5Mode
: 服务器端路由和客户端路由的 URL 以#分隔。例如/foo/bar#/users/alice
,Angular 通过操作锚点来进行路由。 然而html5Mode(true)
将会去除#,URL 变成/foo/bar/users/alice
(这需要浏览器支持 HTML5 的,因为此时 Angular 通过pushState
来进行路由)。 此时服务器对所有的客户端路由的 URL 都需要返回首页(/foo/bar
)视图,再交给 Angular 路由到/foo/bar/users/alice
对应的视图。
1 2 3 4 5
| <div ng-controller="MainController"> Choose: <a href="users">user list</a> | <a href="users/alice">user: alice</a>
<div ng-view></div> </div>
|
注意到模板文件中有一个div[ng-view]
,子页面将会载入到这里。
路由参数
用户列表页面:
1
| app.controller('UserListCtrl', function($scope) {})
|
1 2
| <h1>User List Page</h1>
|
用户页面:
1 2 3
| app.controller('UserCtrl', function($scope, $routeParams) { $scope.params = $routeParams })
|
1 2 3
| <h1>User Page</h1> <span ng-bind="params.userName"></span>
|
我们点击首页的/users/alice
时,将会载入user.html
,span
的值为alice
。$routeParams
提供了当前的路由参数,例如:
1 2 3 4 5 6
|
$routeParams ==> {chapterId:'1', sectionId:'2', search:'moby'}
|
UI-Router
UI-Router 是 Angular-UI 提供的客户端路由框架,它解决了原生的 ng-route 的很多不足:
- 视图不能嵌套。这意味着
$scope
会发生不必要的重新载入。这也是我们在Onboar
d 中引入 ui-route 的原因。
- 同一 URL 下不支持多个视图。这一需求也是常见的:我们希望导航栏用一个视图(和相应的控制器)、内容部分用另一个视图(和相应的控制器)。
UI-Router 提出了$state
的概念。一个$state
是一个当前导航和 UI 的状态,每个$state
需要绑定一个 URL Pattern。 在控制器和模板中,通过改变$state
来进行 URL 的跳转和路由。这是一个简单的例子:
1 2 3 4
| <body ng-controller="MainCtrl"> <section ui-view></section> </body>
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| var myUIRoute = angular.module('MyUIRoute', ['ui.router', 'ngAnimate']) myUIRoute.config(function($stateProvider, $urlRouterProvider) { $urlRouterProvider.otherwise('/contacts') $stateProvider .state('contacts', { url: '/contacts', template: 'contacts.html', controller: 'ContactCtrl' }) .state('contacts.detail', { url: '/contacts/:contactId', templateUrl: 'contacts.detail.html', controller: function($stateParams) { $stateParams.contactId === '42' } }) })
|
当访问/contacts
时,contacts $state
被激活,载入对应的控制器和视图。在 ui-router 时,通常使用$state
来完成页面跳转, 而不是直接操作 URL。例如,在脚本使用$state.go
:
1 2
| $state.go('contacts') $state.go('contacts.detail', { contactId: 42 })
|
在模板中使用ui-sref
(这是一个 Directive):
1 2
| <a ui-sref="contacts">Contacts</a> <a ui-sref="contacts.detail({contactId: 42})">Contact 42</a>
|
嵌套视图
不同于 Angular 原生的ng-route
,ui-router 的视图可以嵌套,视图嵌套通常对应着$state
的嵌套。 contacts.detail
是contacts
的子$state
,contacts.detail.html
也将作为contacts.html
的子页面:
1 2 3
| <h1>My Contacts</h1> <div ui-view></div>
|
1 2
| <span ng-bind="contactId"></span>
|
上述ui-view
的用法和ng-view
看起来很相似,但不同的是ui-view
可以配合$state
进行任意层级的嵌套, 即contacts.detail.html
中仍然可以包含一个ui-view
,它的$state
可能是contacts.detail.hobbies
。
命名视图
在 ui-router 中,一个$state
下可以有多个视图,它们有各自的模板和控制器。这一点也是ng-route
所没有的, 给了前端路由极大的灵活性。来看例子:
1 2 3 4 5 6
| <body> <div ui-view="filters"></div> <div ui-view="tabledata"></div> <div ui-view="graph"></div> </body>
|
这一个模板包含了三个命名的ui-view
,可以给它们分别设置模板和控制器:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| $stateProvider .state('report',{ views: { 'filters': { templateUrl: 'report-filters.html', controller: function($scope){ ... controller stuff just for filters view ... } }, 'tabledata': { templateUrl: 'report-table.html', controller: function($scope){ ... controller stuff just for tabledata view ... } }, 'graph': { templateUrl: 'report-graph.html', controller: function($scope){ ... controller stuff just for graph view ... } } } })
|
综合实例
HTML:
1 2
| //uiRoute.html <div ui-view></div>
|
1 2 3 4 5 6 7
| //index.html <div class="container"> //头部 <div ui-view="topbar"></div> //主体 <div ui-view="main"></div> </div>
|
1 2 3 4 5 6 7 8 9 10
| //topbar.html //顶部 <nav class="navbar navbar-inverse" role="navigation"> <div class="navbar-header"> <a class="navbar-brand" ui-sref="#">ui-router综合实例</a> </div> <ul class="nav navbar-nav"> <li><a ui-sref="index">首页</a></li> <li><a ui-sref="index.usermng">用户管理</a></li> </ul> </nav>
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| //usermng.html //左侧 <div class="row"> <div class="col-md-3"> <div class="row"> <div class="col-md-12"> <div class="list-group"> <a ui-sref="#" class="list-group-item active">用户分类</a> <a ui-sref="index.usermng.highendusers" class="list-group-item" >高端用户</a > </div> </div> </div> <div class="row"> <div class="col-md-12"> <button class="btn btn-primary" ng-click="addUserType()"> 新增用户 </button> </div> </div> </div> <div class="col-md-9"> //用于存放右边部分 <div ui-view></div> </div> </div>
|
javascript:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
| var routerApp = angular.module('routerApp', ['ui.router']) routerApp.config(function($stateProvider, $urlRouterProvider) { $urlRouterProvider.otherwise('/index') $stateProvider .state('index', { url: '/index', views: { '': { templateUrl: 'tpls/index.html' }, 'topbar@index': { templateUrl: 'tpls/topbar.html' }, 'main@index': { templateUrl: 'tpls/home.html' } } }) .state('index.usermng', { url: '/usermng', views: { 'main@index': { templateUrl: 'tpls/usermng.html', controller: function($scope, $state) { $scope.addUserType = function() { $state.go('index.usermng.addusertype') } } } } }) .state('index.usermng.highendusers', { url: '/highendusers', templateUrl: 'tpls/highendusers.html' }) .state('index.usermng.addusertype', { url: '/addusertype', templateUrl: 'tpls3/addusertypeform.html', controller: function($scope, $state) { $scope.backToPrevious = function() { window.history.back() } } }) })
|
转载自:http://harttle.com/2015/06/10/angular-route.html