Angular 5路由守卫报错TypeError: guard is not a function排查求助
Angular 5: 实现Pages路由下持续检查登录状态的方案
我看你现在的需求是用户每次访问pages下的路由时都要检查登录状态,但目前的实现可能没达到预期效果,咱们来一步步排查和修正:
核心问题分析
你当前给pages路由加了CanActivate守卫,但这个守卫只会在首次进入pages路由时触发一次,当用户在pages内部的子路由之间切换时(比如从pages/home跳到pages/settings),守卫不会再次执行,自然就没法持续检查登录状态了。
另外还要确认你的AuthService里的isUserAuthenticated()方法是否能实时反映用户的登录状态——如果它只是读取初始值,没有监听token过期、手动登出这类状态变化,那后续状态改变时守卫也感知不到。
具体解决方案
1. 改用CanActivateChild守卫
这个守卫会在每次进入子路由时都触发检查,完美匹配你“持续检查”的需求。咱们修改守卫类,同时实现CanActivate和CanActivateChild接口:
import { Injectable } from '@angular/core'; import { CanActivate, CanActivateChild, ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router'; import { AuthService } from './auth.service'; import { Router } from '@angular/router'; @Injectable() export class RoutesInterceptor implements CanActivate, CanActivateChild { constructor(private auth: AuthService, private router: Router) {} // 处理父路由的首次进入检查 canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean { return this.checkAuthAndRedirect(state.url); } // 处理所有子路由的切换检查 canActivateChild(childRoute: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean { return this.checkAuthAndRedirect(state.url); } // 统一的登录检查逻辑,抽出来复用 private checkAuthAndRedirect(targetUrl: string): boolean { if (this.auth.isUserAuthenticated()) { return true; } // 未登录的话跳转到登录页,同时保存当前url,方便登录后跳转回来 this.router.navigate(['/login'], { queryParams: { returnUrl: targetUrl } }); return false; } }
2. 更新路由配置
把路由里的canActivate换成canActivateChild,这样pages下的所有子路由都会触发检查:
import { NgModule } from '@angular/core'; import { ExtraOptions, RouterModule, Routes } from '@angular/router'; import { LoginComponent } from './pages/autenticacao/login.component'; import { RoutesInterceptor } from './auth/routes.interceptor'; const routes: Routes = [ { path: 'pages', loadChildren: 'app/pages/pages.module#PagesModule', canActivateChild: [RoutesInterceptor] // 替换为canActivateChild }, { path: 'login', component: LoginComponent }, { path: '', redirectTo: 'pages', pathMatch: 'full' }, { path: '**', redirectTo: 'pages' }, ]; const config: ExtraOptions = { useHash: true, }; @NgModule({ imports: [RouterModule.forRoot(routes, config)], exports: [RouterModule], }) export class AppRoutingModule { }
3. 完善AuthService的状态检查逻辑
确保isUserAuthenticated()能实时验证登录状态,比如检查localStorage里的token是否存在且未过期:
import { Injectable } from '@angular/core'; @Injectable() export class AuthService { isUserAuthenticated(): boolean { const authToken = localStorage.getItem('authToken'); if (!authToken) return false; // 简单的token过期检查(假设是JWT格式) try { const payload = JSON.parse(atob(authToken.split('.')[1])); return payload.exp * 1000 > Date.now(); } catch (err) { // token格式不正确,视为未登录 return false; } } }
额外注意事项
- 你的
AppModule里已经正确注册了守卫和服务,这部分不用改; - 如果pages模块内部有自己的路由配置,不需要再在子路由上重复加守卫,
canActivateChild会自动覆盖所有子路由的检查; - 如果需要在用户登出后立即跳转到登录页,可以在
AuthService里添加一个Subject来监听状态变化,然后在守卫里订阅这个Subject,不过这属于进阶需求,先把基础的持续检查搞定再说~
内容的提问来源于stack exchange,提问作者Erick Zanetti
相关产品推荐
相关产品推荐

