面试题答案
一键面试路由守卫执行顺序
- CanActivate:在进入路由之前触发,用于判断是否可以激活该路由。如果所有CanActivate守卫都返回true,则继续导航,否则导航被阻止。
- CanActivateChild:在进入子路由之前触发,用于判断是否可以激活子路由。同样,若所有CanActivateChild守卫都返回true,才允许进入子路由。
- Resolve:在路由激活之前触发,用于在路由激活前获取或解析数据。例如,在显示产品详情页之前,通过Resolve提前获取产品数据。
- CanDeactivate:在离开当前路由时触发,用于判断是否可以离开当前路由。比如,当用户在表单中输入未保存的数据时,可通过此守卫提示用户是否保存。
各守卫具体作用
- CanActivate:
- 作用:决定是否允许导航到某个路由。常用于权限验证,例如只有登录用户才能访问特定页面。
- 示例:
import { Injectable } from '@angular/core';
import { CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot, Router } from '@angular/router';
import { AuthService } from './auth.service';
@Injectable({
providedIn: 'root'
})
export class AuthGuard implements CanActivate {
constructor(private authService: AuthService, private router: Router) {}
canActivate(
next: ActivatedRouteSnapshot,
state: RouterStateSnapshot): boolean {
if (this.authService.isLoggedIn()) {
return true;
} else {
this.router.navigate(['/login']);
return false;
}
}
}
- CanActivateChild:
- 作用:与CanActivate类似,但作用于子路由。当导航到子路由时,会触发此守卫。
- 示例:假设存在管理模块的子路由,只有管理员角色能访问。
import { Injectable } from '@angular/core';
import { CanActivateChild, ActivatedRouteSnapshot, RouterStateSnapshot, Router } from '@angular/router';
import { AuthService } from './auth.service';
@Injectable({
providedIn: 'root'
})
export class AdminGuard implements CanActivateChild {
constructor(private authService: AuthService, private router: Router) {}
canActivateChild(
next: ActivatedRouteSnapshot,
state: RouterStateSnapshot): boolean {
if (this.authService.isAdmin()) {
return true;
} else {
this.router.navigate(['/home']);
return false;
}
}
}
- Resolve:
- 作用:在路由激活前解析数据,确保组件在渲染前能获取到所需数据。这样可避免组件加载后再异步获取数据导致的闪烁等问题。
- 示例:在显示用户详情页时,提前获取用户数据。
import { Injectable } from '@angular/core';
import { Resolve, ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router';
import { UserService } from './user.service';
@Injectable({
providedIn: 'root'
})
export class UserResolver implements Resolve<any> {
constructor(private userService: UserService) {}
resolve(
route: ActivatedRouteSnapshot,
state: RouterStateSnapshot) {
return this.userService.getUser(route.params['id']);
}
}
- CanDeactivate:
- 作用:在离开当前路由时进行确认,常用于防止用户意外离开未保存数据的页面。
- 示例:当用户在编辑文章页面未保存文章就尝试离开时,提示用户。
import { Injectable } from '@angular/core';
import { CanDeactivate } from '@angular/router';
import { ArticleEditComponent } from './article - edit.component';
import { Observable } from 'rxjs';
@Injectable({
providedIn: 'root'
})
export class ArticleEditGuard implements CanDeactivate<ArticleEditComponent> {
canDeactivate(
component: ArticleEditComponent,
currentRoute: ActivatedRouteSnapshot,
currentState: RouterStateSnapshot,
nextState?: RouterStateSnapshot): Observable<boolean> | Promise<boolean> | boolean {
return component.canLeave();
}
}
在复杂路由结构下的应用
假设应用有多层嵌套路由,如/admin/dashboard/user/:id
。
- 权限验证:使用CanActivate在
/admin
路由级别验证用户是否为管理员,在/admin/dashboard
使用CanActivateChild进一步验证权限。 - 数据加载:在
/admin/dashboard/user/:id
路由使用Resolve提前获取用户详细数据,确保UserDetailComponent
能直接使用数据渲染。 - 防止意外离开:若
UserDetailComponent
有可编辑区域,在用户离开时,通过CanDeactivate提示用户保存更改。
通过合理组合这些路由守卫,能确保复杂路由结构下导航的正确性和数据加载的合理性。