angular-ui-router使用

github源码地址:https://github.com/angular-ui/ui-router

api地址 http://angular-ui.github.io/ui-router/site

安装

1
npm install --save angular-ui-router

使用angular-ui-router

备注: 以下所有示例代码来源于个人所写的练习.

地址为:https://github.com/silence717/angular-webpack-demo

导入angular-ui-router
1
import uiRouter from 'angular-ui-router';
在angular.module中注入angular-ui-router
1
angular.module('app',[uiRouter]);
为了方便使用,将$state与$stateParams全部挂载到$rootScope,在angular.module中初始化
1
2
3
4
5
6
function runBlock($rootScope, $state, $stateParams) {
'ngInject';
$rootScope.$state = $state;
$rootScope.$stateParams = $stateParams;
}
定义路由规则,在angular.module中配置路由规则
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
export function routerConfig($urlRouterProvider) {
'ngInject';
// 默认路由设置
$urlRouterProvider.otherwise('/home');
// 无视浏览器中 url末尾的"/"
// 设置时 url, 末尾不要添加 "/"
$urlRouterProvider.rule(($injector, $location) => {
const path = $location.path();
const hashTrailingSlash = path[path.length -1] === '/';
if (hashTrailingSlash) {
return path.slice(0, path.length -1);
}
});
}
基于以上两部分的操作,完整的app初始化代码为
1
2
3
4
angular
.module('app', [uiRouter])
.config(routerConfig)
.run(runBlock);
业务模块路由定义配置,我们通常建议将路由分散到自己的模块管理,所以只以单个作为示例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
export const HomeRouter = {
state: 'home',
config: {
url: '/home',
views: {
'@': {
template: homeTpl,
controller: 'HomeController',
controllerAs: 'vm'
}
},
title: '好玩的app'
}
};
业务入口主文件导入,并且在angular.module中配置
1
2
3
4
5
6
7
8
9
10
11
import {HomeRouter} from './Routers';
function config($stateProvider) {
'ngInject';
$stateProvider.state(HomeRouter.state, HomeRouter.config);
}
export default angular
.module('app.home', [])
.config(config)
.name;
页面的html如何书写
1
2
3
4
5
6
<ul class="nav navbar-nav">
<li ui-sref-active="active"><a ui-sref="home">首页</a></li>
<li ui-sref-active="active"><a ui-sref="album">相册</a></li>
<li ui-sref-active="active"><a ui-sref="user.baseInfo">个人中心</a></li>
</ul>
<div ui-view=""></div>

在这里做一个简单常用的API的解释

directive

ui-view: The ui-view directive tells $state where to place your templates.

ui-view使用有三种,分别为:

  1. as element:

    1
    <ui-view></ui-view>
  2. as attribute:

    1
    <ANY ui-view ></ANY>
  3. as class:

    1
    <ANY class="ui-view"></ANY>

具体里面的参数不做介绍,自己查阅官方文档

上面的html代码会被compile为:

1
2
3
4
5
<ul class="nav navbar-nav">
<li ui-sref-active="active" ui-sref-active-eq="" class="active"><a ui-sref="home" href="#/home">首页</a></li>
<li ui-sref-active="active" class=""><a ui-sref="album" href="#/album">相册</a></li>
<li ui-sref-active="active" class=""><a ui-sref="user.baseInfo" href="#/user/baseInfo">个人中心</a></li>
</ul>

$state使用

Methods

get 获取当前state的配置信息
1
<a href="javascript:;" ng-click="vm.getConfig();">获取state配置</a>
1
2
3
let config = this.state.get('user');
console.log(config);
// => Object {url: "/user", views: Object, title: "个人中心", name: "user"}...
go 跳转到一个新的state
1
<a href="javascript:;" ng-click="vm.goUserCenter();">这是一个跳转链接...</a>
1
2
3
4
// 不带参数跳转
this.state.go('user.baseInfo');
// 带参数跳转
this.state.go('album.detail', {id: 1});
href 获取到当前state的href值
1
2
console.log(this.state.href('album.detail', {id: 0}));
// => #/album/0
includes 获取当前state是否包含某些state
1
2
console.log(this.state.includes('album'));
// => false
is Similar to $state.includes, but only checks for the full state name
1
console.log(this.state.is('home')); //=> true

events

$stateChangeStart 路由发生改变
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
function stateChangeStart($rootScope) {
$rootScope.$on('$stateChangeStart',
(event, toState, toParams, fromState, fromParams) => {
// event.preventDefault();
console.log('开始改变=====');
console.log(toState);
console.log(toParams);
console.log(fromState);
console.log(fromParams);
// 开始改变=====
// app.js:48Object {url: "/home", views: Object, title: "好玩的app", name: "home"}
// app.js:49Object {}
// app.js:50Object {name: "", url: "^", views: null, abstract: true}
// app.js:51Object {}
// client.js:55 [HMR] connected
});
}
$stateChangeError 路由转变出错,参数基本与$stateChangeStart一致,多一个error参数
$stateChangeSuccess 路由转向成功,参数与$stateChangeStart完全一致
$stateNotFound 未找到路由,demo copy于参照官网
1
2
3
4
5
6
7
8
9
10
// somewhere, assume lazy.state has not been defined
$state.go("lazy.state", {a:1, b:2}, {inherit:false});
// somewhere else
$scope.$on('$stateNotFound',
function(event, unfoundState, fromState, fromParams) {
console.log(unfoundState.to); // "lazy.state"
console.log(unfoundState.toParams); // {a:1, b:2}
console.log(unfoundState.options); // {inherit:false} + default options
})
onEnter 可以配置进入路由to do something
1
2
3
onEnter: function() {
console.log('enter user.footprint state');
}
onExit 退出路由做什么
1
2
3
4
onExit: function() {
// 用于初始化一些数据什么的,清空表单...
console.log('exit user.footprint state');
}

部分知识点单列:

一、问: 多个页面可能使用相同的html模板,我们是要同样的代码写N遍吗? 答案肯定不是.那么问题来了,一个页面有多个模板文件,肿么办?

  1. 在html中给ui-view添加名字

    1
    2
    3
    <div ui-view="content"></div>
    <div ng-show="vm.isShowThumb" class="module-content" ui-view="thumbList"></div>
    <div ng-show="vm.isShowDetail" ui-view="detailList"></div>
  2. 在路由配置中添加配置信息

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    export const UserFootprintRouter = {
    state: 'user.footprint',
    config: {
    url: '/footprint',
    views: {
    'content@user': {
    template: footPrintTpl,
    controller: 'FootprintController',
    controllerAs: 'vm'
    },
    'thumbList@user.footprint': {
    template: thumbListTpl
    },
    'detailList@user.footprint': {
    template: detailListTpl
    }
    },
    title: '我的足迹'
    }
    };

个人理解就是: viewname@statename去设置template

二、 $stateParams使用,^^最后一个点

先看代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
export const AlbumDetailRouter = {
state: 'album.detail',
config: {
url: '/:id',
views: {
'@': {
template: albumDetailTpl,
controller: 'PhotoController',
controllerAs: 'vm'
}
},
title: '单张照片show'
}
};

问: 我们经常会需要用到路由去传参,例如编辑一条信息,获取单个信息,应该如何去做呢?

答: angular-ui-router提供了一个$stateParams的service,可直接获取.在controller中的使用示例

1
2
3
4
5
6
7
8
9
10
11
export default class PhotoController {
constructor(photoResource, $stateParams) {
let vm = this;
photoResource.success(data => {
vm.detail = data[$stateParams.id];
})
}
}

有人肯定会疑问,$stateParams从何而来,在上面我们给angular.module中已经将其初始化,挂在到$rootScope.

三、这次真的是最后一个点了 most important: $urlRouterProvider

  1. when() for redirection

    1
    2
    3
    app.config(function($urlRouterProvider){
    $urlRouterProvider.when('', '/index');
    });
  2. otherwise() for invalid routes

    1
    2
    3
    app.config(function($urlRouterProvider){
    $urlRouterProvider.otherwise('/home');
    });
it’s over! 所有以上仅代表个人理解,如有不对,请指出,虚心接受改正错误!
杨芳<br>前端一枚<br>背包客,热爱旅行,喜欢摄影<br>轻微洁癖,强迫症,电话恐惧症患者!