Angular 17:如何将原CanActivate守卫适配为CanActivateFn?
将Angular 17中废弃的CanActivate迁移为CanActivateFn
迁移后的函数式守卫代码
import { ActivatedRouteSnapshot, CanActivateFn, Router, RouterStateSnapshot } from '@angular/router'; import { inject } from '@angular/core'; import { AutorizacaoService } from '../services/autorizacao.service'; export const autorizadoGuard: CanActivateFn = ( route: ActivatedRouteSnapshot, state: RouterStateSnapshot ) => { const autorizadoService = inject(AutorizacaoService); const routerService = inject(Router); const usuarioEstaLogado = autorizadoService.obterLoginStatus(); if (usuarioEstaLogado) { return true; } // 推荐使用createUrlTree替代navigate,避免导航异步竞态问题 return routerService.createUrlTree(['/login']); };
关键变化说明
- 移除类结构:不再需要
@Injectable装饰器和实现CanActivate接口的类,改为直接导出一个类型为CanActivateFn的函数。 - 依赖注入方式调整:使用Angular内置的
inject()函数在函数内部获取所需服务,替代原构造函数注入逻辑。 - 返回值优化:官方推荐返回
UrlTree(通过createUrlTree)而非先调用navigate再返回false,确保导航逻辑同步执行,避免潜在的异步问题。
路由配置更新
原类守卫的路由引用方式:
{ path: 'protected', component: ProtectedComponent, canActivate: [AutorizadoGuard] }
改为引用函数式守卫:
{ path: 'protected', component: ProtectedComponent, canActivate: [autorizadoGuard] }
异步场景适配(可选)
如果obterLoginStatus返回的是Observable<boolean>或Promise<boolean>,只需调整返回逻辑即可,CanActivateFn天然支持异步返回:
import { map } from 'rxjs'; export const autorizadoGuard: CanActivateFn = (route, state) => { const autorizadoService = inject(AutorizacaoService); const routerService = inject(Router); return autorizadoService.obterLoginStatus().pipe( map(logado => logado ? true : routerService.createUrlTree(['/login'])) ); };
内容的提问来源于stack exchange,提问作者vinudev
相关产品推荐
相关产品推荐

