Angular刷新或直接输入URL时ActivatedRouteSnapshot的data属性为空问题
问题根因
你在父路由(path: '')和子路由上都配置了同一个AuthGuard,Angular路由守卫的执行顺序是从上到下、先父后子:
- 页面刷新/直接输入URL访问时,首先触发父路由的
AuthGuard,此时传入canActivate方法的route参数是父路由的ActivatedRouteSnapshot实例,本身没有配置data属性,自然读取不到子路由的permissions和路径配置 - 应用内点击路由链接跳转时,父路由守卫已经在前序导航中完成校验,触发子路由守卫时传入的是子路由的快照,所以可以正常读取
data
解决方案
方案1:调整守卫挂载逻辑(最推荐)
移除父路由上的AuthGuard,改用canActivateChild配置统管所有子路由的鉴权,守卫触发时会直接传入匹配到的子路由快照:
const routes: Routes = [ { path: '', canActivateChild: [AuthGuard], // 替换原来的canActivate component: DefaultLayoutComponent, children: [ // 子路由配置保持不变 ] } ];
修改后子路由的AuthGuard可以保留也可以移除,canActivateChild会对所有子路由生效。
方案2:父守卫中递归获取最深子路由快照
如果必须保留父路由的canActivate配置,可以在守卫中递归读取到最终匹配的子路由快照再拿配置:
@Injectable({ providedIn: 'root' }) export class AuthGuard implements CanActivate { constructor( private router: Router, private accountService: AccountService ) { } // 注意:守卫不需要注入ActivatedRoute,直接用入参的route即可 canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) { // 递归获取最深层级的子路由快照 const getDeepestRoute = (snapshot: ActivatedRouteSnapshot): ActivatedRouteSnapshot => { return snapshot.firstChild ? getDeepestRoute(snapshot.firstChild) : snapshot; } const targetRoute = getDeepestRoute(route); const path = targetRoute.routeConfig?.path; const permissions = targetRoute.data["permissions"]; // 后续鉴权逻辑 } }
内容的提问来源于stack exchange,提问作者Developerzzz
相关产品推荐
相关产品推荐

