首页 > 解决方案 > 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。


应用程序路由.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 11)

标签: angularlazy-loadingangular-routingangular-lazyloading

解决方案


首先,您可以添加两个保护,以便未经授权的用户无法加载和访问您的秘密模块:

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)
  },
];

您可以在文档中阅读更多信息


推荐阅读