Angular 5无组件路由跳转子路由时Route Guard触发异常问题
为什么无组件父路由的CanActivate守卫只在应用启动时触发?
这是个非常典型的Angular路由守卫行为疑问,核心原因在于Angular路由守卫的触发逻辑和路由激活机制:
1. 单个路由配置下CanActivate的触发逻辑
当你给每个路由(comp1、comp2、空路径)单独添加canActivate: [AuthGuard]时,每次通过routerLink跳转到这些路由,本质都是激活一个全新的路由节点。Angular会在激活每个目标路由前,执行其配置的canActivate守卫,所以每次跳转都会触发AuthGuard。
2. 无组件父路由的CanActivate触发限制
而在无组件父路由的配置中,canActivate是绑定在父路由上的:
- 应用启动时,会匹配到空路径的父路由并激活它,此时会触发父路由的
canActivate守卫。 - 当你在子路由之间切换(比如从
comp1到comp2)时,父路由已经处于激活状态,Angular只会更新子路由的视图,不会重新激活父路由。由于canActivate只在路由被激活时触发,所以后续的子路由切换不会再调用AuthGuard。
3. 如何实现子路由切换时也触发守卫?
如果希望每次切换子路由都执行权限验证,你需要使用canActivateChild守卫,而不是canActivate。把守卫配置在父路由的canActivateChild属性上,Angular会在任何子路由被激活前触发这个守卫,包括子路由之间的切换:
const routes: Route[] = [ { path: '', canActivateChild: [AuthGuard], // 替换为canActivateChild children: [ { path: 'comp1', component: Comp1Component}, { path: 'comp2', component: Comp2Component} ] } ]
对应的AuthGuard需要实现CanActivateChild接口(其实CanActivate和CanActivateChild的方法签名一致,所以你只需要让守卫类同时实现这两个接口,或者直接复用canActivate的逻辑即可):
import { Injectable } from '@angular/core'; import { CanActivate, CanActivateChild, ActivatedRouteSnapshot, RouterStateSnapshot, UrlTree } from '@angular/router'; import { Observable } from 'rxjs'; @Injectable({ providedIn: 'root' }) export class AuthGuard implements CanActivate, CanActivateChild { canActivate( route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree { // 你的权限验证逻辑 return true; } canActivateChild( childRoute: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree { // 直接复用canActivate的验证逻辑 return this.canActivate(childRoute, state); } }
这样修改后,不管是首次进入子路由,还是在子路由之间切换,AuthGuard都会被触发。
内容的提问来源于stack exchange,提问作者ochs.tobi
相关产品推荐
相关产品推荐

