假设这样一种需要用到两个异步路由守卫场景
1.需要判定用户登录了没有,如果没有需要跳转登录页面(login)
2.如果用户登录了,判断用户有没有权限,如果没权限,则跳转到访问拒绝(deny)
多个路由守卫的优先级(angular7+支持)
- 父路由守卫的优先级比子的高
- canActivateChild数组前面的路由守卫比后面的拥有更高的优先级
- 优先级高的意思是即使UserGuard异步请求先回来,也要等LoginGuard的请求回来才决定跳转哪个页面(等待过程是白屏)
canActivateChild: [LoginGuard, UserGuard],
LoginGuard返回true | LoginGuard返回跳转 | |
UserGuard返回true | 该页面可以正常访问 | 跳转login页面 |
UserGuard返回跳转 | 跳转deny页面 | 跳转login页面 |
LoginGuard
import { Injectable } from '@angular/core';
import { CanActivateChild, ActivatedRouteSnapshot, RouterStateSnapshot, UrlTree, Router } from '@angular/router';
import { Observable } from 'rxjs';
@Injectable({
providedIn: 'root'
})
export class LoginGuard implements CanActivateChild {
constructor(private router: Router) { }
canActivateChild(
route: ActivatedRouteSnapshot,
state: RouterStateSnapshot): Promise<boolean | UrlTree> | boolean | UrlTree {
console.log('login路由守卫');
return new Promise((resolve, reject) => {
this.getLogin().then(res => {
if (res) {
resolve(true);
} else {
console.log('跳转到login');
resolve(this.router.parseUrl('/user/login'));
}
});
});
}
// 用settimeout模拟异步请求
getLogin(): Promise<boolean> {
const timeout = 2000;
const isLogin = false;
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(isLogin);
}, timeout);
});
}
}
UserGuard
import { Injectable } from '@angular/core';
import { CanActivateChild, ActivatedRouteSnapshot, RouterStateSnapshot, UrlTree, Router } from '@angular/router';
import { Observable } from 'rxjs';
@Injectable({
providedIn: 'root'
})
export class UserGuard implements CanActivateChild {
constructor(private router: Router) { }
canActivateChild(
route: ActivatedRouteSnapshot,
state: RouterStateSnapshot): Promise<boolean | UrlTree> | boolean | UrlTree {
console.log('user路由守卫');
return new Promise((resolve, reject) => {
this.getUser().then(res => {
if (res) {
resolve(true);
} else {
console.log('跳转到deny');
resolve(this.router.parseUrl('/user/deny'));
}
});
});
}
// 用settimeout模拟异步请求
getUser(): Promise<boolean> {
const timeout = 1000;
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(false);
}, timeout);
});
}
}