如何通过构造函数依赖注入在 Angular 16 中使用 CanActivateFn

jos*_*eme 9 angular angular-router-guards angular16

如何通过 DI 使用 Angular 16 中最新的 CanActivateFn?

最近的 Angular 16 使用函数而不是类来实现 canactivate 功能。这是我下面的代码。如何添加通常位于函数构造函数中的 DI?

CanActivateFn函数代码:

export const authGuard: CanActivateFn = (
  next: ActivatedRouteSnapshot,
  state: RouterStateSnapshot
) => {
  return inject(TokenService).authenticated.pipe(
    take(1),
    map((status) => {
      console.log('auth status: ', status);
      if (!status) {
        return inject(Router).createUrlTree(['/login']);
      }
      return true;
    })
  );
};
Run Code Online (Sandbox Code Playgroud)

路线设置:

const routes: Routes = [
  {
    path: '',
    component: DefaultComponent,
    canActivate: [authGuard],
    children: [
      {
        path: '',
        component: DashboardComponent,
        data: { title: 'My Dashboard' },
      },
]
Run Code Online (Sandbox Code Playgroud)

jos*_*eme 8

我想到了。我试过这个。我更新了我的服务 BehavoirSubject 变量以使用 signal()。

export class TokenService {
  authenticated = signal(false);
}
Run Code Online (Sandbox Code Playgroud)

然后我使用inject()函数更新了我的authGuard函数。

export const authGuard: CanActivateFn = (
  route: ActivatedRouteSnapshot,
  state: RouterStateSnapshot
) => {
  // console.log('guard status: ', inject(TokenService).authenticated());

  return inject(TokenService).authenticated()
    ? true
    : inject(Router).createUrlTree(['/auth/login']);
};
Run Code Online (Sandbox Code Playgroud)

这种方法对我有用。


小智 2

要将 DI 添加到 Angular 16 中的 authGuard 函数,您可以创建一个工厂函数,该函数返回注入了依赖项的 authGuard 函数。这是一个例子:

import { Injectable } from '@angular/core';
import {
  CanActivateFn,
  ActivatedRouteSnapshot,
  RouterStateSnapshot,
  Router,
} from '@angular/router';
import { TokenService } from './token.service';
import { take, map } from 'rxjs/operators';

function authGuardFactory(tokenService: TokenService, router: Router): CanActivateFn {
  return (
    next: ActivatedRouteSnapshot,
    state: RouterStateSnapshot
  ) => {
    return tokenService.authenticated.pipe(
      take(1),
      map((status) => {
        console.log('auth status: ', status);
        if (!status) {
          return router.createUrlTree(['/login']);
        }
        return true;
      })
    );
  };
}

@Injectable({
  providedIn: 'root',
})
export class AuthGuard {
  constructor(private tokenService: TokenService, private router: Router) {}

  canActivate: [authGuardFactory(this.tokenService, this.router)];
}
Run Code Online (Sandbox Code Playgroud)

在此示例中,我们定义了一个 authGuardFactory 函数,该函数接受依赖项 TokenService 和 Router,并返回 authGuard 函数以及使用 Inject() 注入的依赖项。然后,我们使用 authGuardFactory 函数作为 AuthGuard 类中的 canActivate 属性。这样,我们仍然可以在 authGuard 函数中使用依赖注入,即使它是一个函数而不是一个类。