如何用CanMatchFn和CanActivateFn实现Angular认证守卫(类转函数)
问题描述
我有如下Angular AuthGuard:
@Injectable({ providedIn: 'root', }) export class AuthGuard implements CanActivate, CanLoad { constructor(private authService: AuthService, private router: Router) {} canActivate( next: ActivatedRouteSnapshot, state: RouterStateSnapshot, ): | Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree { return this.isAuthenticated(); } canLoad( route: Route, segments: UrlSegment[], ): | boolean | UrlTree | Observable<boolean | UrlTree> | Promise<boolean | UrlTree> { return this.isAuthenticated(); } isAuthenticated(): | boolean | UrlTree | Observable<boolean | UrlTree> | Promise<boolean | UrlTree> { return this.authService.isAuthenticated$.pipe( take(1), tap((isAuthenticated: boolean) => { if (!isAuthenticated) { this.router.navigate(['/account/login']); } }), ); } }
我已升级至Angular 15:
Angular CLI: 15.2.0 Node: 16.19.1 Package Manager: npm 8.19.3 OS: darwin x64 Angular: 15.2.0 Package Version --------------------------------------------------------- @angular-devkit/core 15.2.0 @angular-devkit/schematics 15.2.0 @schematics/angular 15.2.0
现在收到TS弃用提示:CanActivate已弃用,建议使用CanActivateFn;CanLoad已弃用,建议使用CanMatchFn。我尝试查找如何用CanActivateFn和CanMatchFn实现AuthGuard,但找不到能实现未认证时跳转至/account/login路由功能的合适资源,请问如何正确实现这类简易Angular认证守卫?
解决方案
Angular 15+推荐使用函数式守卫替代类守卫,核心是用inject()函数获取依赖,直接返回认证判断结果(包含路由跳转逻辑)。
1. 提取通用认证逻辑
先封装通用的认证校验函数,返回Observable<boolean | UrlTree>类型:
import { inject } from '@angular/core'; import { Router, UrlTree } from '@angular/router'; import { Observable, take, map } from 'rxjs'; import { AuthService } from './auth.service'; const checkAuthentication = (): Observable<boolean | UrlTree> => { const authService = inject(AuthService); const router = inject(Router); return authService.isAuthenticated$.pipe( take(1), map((isAuthenticated: boolean) => { // 未认证时返回UrlTree,Angular会自动处理跳转 return isAuthenticated || router.createUrlTree(['/account/login']); }) ); };
注意:不再使用
tap调用router.navigate,直接返回UrlTree是函数式守卫的标准写法,更符合守卫的设计逻辑。
2. 定义守卫函数
基于通用逻辑创建CanActivateFn和CanMatchFn:
import { CanActivateFn, CanMatchFn } from '@angular/router'; export const authActivateGuard: CanActivateFn = () => { return checkAuthentication(); }; export const authMatchGuard: CanMatchFn = () => { return checkAuthentication(); };
3. 路由配置中使用
修改路由配置,替换原类守卫为新的函数式守卫:
import { Routes } from '@angular/router'; import { authActivateGuard, authMatchGuard } from './auth.guard'; const routes: Routes = [ { path: 'dashboard', component: DashboardComponent, // 替代原canActivate: [AuthGuard] canActivate: [authActivateGuard], // 替代原canLoad: [AuthGuard] canMatch: [authMatchGuard] }, // 其他路由配置... ];
核心要点
- 函数式守卫无需
@Injectable装饰器,通过inject()直接获取依赖,Angular自动处理注入。 CanMatchFn完全替代CanLoad的功能,用于懒加载路由的权限校验。- 返回
UrlTree是Angular官方推荐的跳转方式,确保守卫逻辑的一致性和可预测性。
内容的提问来源于stack exchange,提问作者Lorraine Ram-El
相关产品推荐
相关产品推荐

