Angular 15中CanActivate已弃用,如何修复Auth Guard问题?
解决Angular 15中CanActivate已弃用的问题
升级到Angular 15后,原有的类式AuthGuard实现CanActivate接口时会触发CanActivate is deprecated的错误提示,原代码如下:
原AuthGuard代码
import { Injectable } from '@angular/core'; import { CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot, UrlTree, Router } from '@angular/router'; import { Observable } from 'rxjs'; import { ToastrService } from 'ngx-toastr'; import { AuthService } from 'src/app/features/auth/services/auth.service'; import { map } from 'rxjs/operators'; @Injectable({ providedIn: 'root' }) export class AuthGuard implements CanActivate { constructor(private authService: AuthService, private toastr: ToastrService, private router: Router) { } canActivate( route: ActivatedRouteSnapshot, state: RouterStateSnapshot ): | Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree { if (!this.authService.isLoggedIn()) { this.toastr.info('Please Log In!'); this.router.navigate(['/auth']); return false; } // logged in, so return true this.authService.isLoggedIn(); return true; } }
解决办法
方法一:使用函数式守卫(Angular 15+官方推荐)
Angular 15开始推荐使用函数式守卫替代类式守卫,直接定义一个CanActivateFn类型的函数即可:
import { inject } from '@angular/core'; import { CanActivateFn, Router } from '@angular/router'; import { ToastrService } from 'ngx-toastr'; import { AuthService } from 'src/app/features/auth/services/auth.service'; export const authGuard: CanActivateFn = (route, state) => { // 使用inject获取依赖实例 const authService = inject(AuthService); const toastr = inject(ToastrService); const router = inject(Router); if (!authService.isLoggedIn()) { toastr.info('Please Log In!'); router.navigate(['/auth']); return false; } authService.isLoggedIn(); return true; };
然后在路由配置中替换原来的类引用:
// 原路由配置 { path: 'protected', component: ProtectedComponent, canActivate: [AuthGuard] // 旧写法 } // 修改后 { path: 'protected', component: ProtectedComponent, canActivate: [authGuard] // 使用函数式守卫 }
方法二:改用CanActivateChild接口(临时兼容方案)
如果暂时不想重构为函数式守卫,可以将类实现的接口从CanActivate改为CanActivateChild,该接口目前未被弃用:
import { Injectable } from '@angular/core'; import { CanActivateChild, ActivatedRouteSnapshot, RouterStateSnapshot, UrlTree, Router } from '@angular/router'; import { Observable } from 'rxjs'; import { ToastrService } from 'ngx-toastr'; import { AuthService } from 'src/app/features/auth/services/auth.service'; @Injectable({ providedIn: 'root' }) export class AuthGuard implements CanActivateChild { constructor(private authService: AuthService, private toastr: ToastrService, private router: Router) { } canActivateChild( route: ActivatedRouteSnapshot, state: RouterStateSnapshot ): | Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree { if (!this.authService.isLoggedIn()) { this.toastr.info('Please Log In!'); this.router.navigate(['/auth']); return false; } this.authService.isLoggedIn(); return true; } }
路由配置中对应改为canActivateChild:
{ path: 'protected', component: ProtectedComponent, canActivateChild: [AuthGuard] }
注意:官方长期规划中类式守卫会逐步被淘汰,建议优先采用函数式守卫方案。
内容的提问来源于stack exchange,提问作者Bami
相关产品推荐
相关产品推荐

