Angular - 延迟加载条件路由

Angular - Lazy load conditional route

我正在构建一个应用程序,我在应用程序启动时对用户进行身份验证。基于用户是否已通过身份验证,我想延迟加载不同的 angular 模块。

在上下文中:

app.component.ts

@Component({
  template: `
    <app-splash-screen *ngIf="isAuthenticating$ | async; else main"></app-splash-screen>

    <ng-template #main>
      <router-outlet></router-outlet>
    </ng-template>
  `
})
export class AppComponent implements OnInit {
  readonly isAuthenticating$ = this.authFacade.isAuthenticating$;

  constructor(private readonly authFacade: AuthFacade) {}

  ngOnInit(): void {
    this.authFacade.authenticate();
  }
}

这是我启动我的身份验证逻辑的地方,该逻辑在不确定的时间点完成。如果需要,我可以在完成 Observable 后选择加入。

身份验证完成后,我将路由器出口加载到 DOM。


应用-routing.module.ts

const routes: Routes = [
  // Lazy-load, when authentication succeeds
  {
    path: '',
    pathMatch: 'full',
    loadChildren: () => import('@my-application/secret').then(m => m.SecretModule)
  },

  // Lazy-load, when authentication fails
  {
    path: 'home',
    loadChildren: () => import('@my-application/home').then(m => m.HomeModule)
  },
];

@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule]
})
export class AppRoutingModule { }

这些是我的顶级路线。现在,我想要实现的是当用户通过身份验证时,延迟加载 SecretModule 并显示其内容。

另一方面,当身份验证失败时,我想将用户导航到主页并延迟加载 HomeModule

现在我看到一个关于 SecretModule 的空白路由的问题。我能想到的一种解决方法是在身份验证完成后在其他地方手动实现此条件路由逻辑,而不是 'angular way'.

您认为实现上述逻辑的最佳方法是什么?

(我用的是Angular11)

首先你可以添加两个守卫,这样未经授权的用户就无法加载和访问你的秘密模块:

auth.guard.ts

@Injectable({
  providedIn: 'root'
})
export class AuthGuard implements CanActivate, CanLoad {
  constructor(
    private router: Router,
    private authService: AuthService, // I asume u got some kind of auth service written
  ) {}

  canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Promise<boolean | UrlTree> | boolean | UrlTree {
    console.log('Trying to activate admin route');
    return this.checkAccess();
  }

  canLoad(route: Route, segments: UrlSegment[]): Promise<boolean | UrlTree> | boolean | UrlTree {
    console.log('Trying to load admin  route');
    return this.checkAccess();
  }

  private checkAccess(): Promise<boolean | UrlTree> {
    return new Promise<boolean | UrlTree>(async (resolve) => {
      // Do your check here if the user is authenticated
      const isLoggedIn = await this.authService.isLoggedIn();

      // If user is not authenticated he gets redirected to home page
      resolve(isLoggedIn ? true : this.router.createUrlTree(['home']));
    });
  }
}

然后在你的秘密路线上使用你的守卫:

const routes: Routes = [
  // Lazy-load, when authentication succeeds
  {
    path: '',
    pathMatch: 'full',
    loadChildren: () => import('@my-application/secret').then(m => m.SecretModule),
    canLoad: [AuthGuard],
    canActivate: [AuthGuard],
  },

  // Lazy-load, when authentication fails
  {
    path: 'home',
    loadChildren: () => import('@my-application/home').then(m => m.HomeModule)
  },
];

您可以在文档中阅读更多内容