Angular 2+ : canLoad 用法

Angular 2+ : canLoad usage

我正在尝试对路由使用 canLoad 函数,但它似乎不起作用。

我不知道为什么,也许你不能将它与 canActivate 或其他东西一起使用,但由于我不知道,我想有人会在这里。

代码运行,当使用 aot 编译时我得到这个:

chunk {admin.module} admin.module.chunk.js, admin.module.chunk.js.map () 28 kB {main} {pilotage.module} {suiviprod.module}
chunk {inline} inline.bundle.js, inline.bundle.js.map (inline) 5.83 kB [entry]
chunk {main} main.bundle.js, main.bundle.js.map (main) 3.5 MB {vendor} [initial]
chunk {pilotage.module} pilotage.module.chunk.js, pilotage.module.chunk.js.map () 17.2 kB {admin.module} {main} {suiviprod.module}
chunk {styles} styles.bundle.js, styles.bundle.js.map (styles) 267 kB {inline} [initial]
chunk {suiviprod.module} suiviprod.module.chunk.js, suiviprod.module.chunk.js.map () 20.4 kB {admin.module} {main} {pilotage.module}
chunk {vendor} vendor.bundle.js, vendor.bundle.js.map (vendor) 5.52 MB [initial]

但是当我转到模块时,控制台日志没有完成。

这是我的路线代码:

logged.module(主路由,看成app.module)

export const loggedRoutes: Routes = [
  {
    path: 'logged', component: LoggedComponent, canActivate: [AuthGuardService], canActivateChild: [AuthGuardService], children: [
      { path: 'profile', component: ProfileComponent, children: [] },
      ...adminRoutes,
      ...mainRoutes,
      ...pilotageRoutes,
      ...suiviProdRoutes,
      { path: 'admin', loadChildren: 'app/logged/admin/admin.module#AdminModule', canLoad: [AdminGuardService] },
      { path: 'pilotage', loadChildren: 'app/logged/pilotage/pilotage.module#PilotageModule', canLoad: [AdminGuardService] },
      { path: 'suiviprod', loadChildren: 'app/logged/suiviprod/suiviprod.module#SuiviprodModule', canLoad: [AdminGuardService] },
      { path: '', redirectTo: '/logged/main/error', pathMatch: 'prefix' }
    ]
  },
];

admin.module(suiviprod 和 pilotage 是一样的,只是航线和组件不同)

export const adminRoutes: Routes = [
  {
    path: 'admin', component: AdminComponent, canActivate: [AdminGuardService], canActivateChild: [AdminGuardService], children: [
      { path: 'validation', component: ValidationComponent, children: [] },
      { path: 'dashboard', component: DashboardComponent, children: [] },
      { path: 'user/:id', component: UserComponent, children: [] },
      { path: 'users', component: UsersComponent, children: [] },
      { path: 'params', component: ParamsComponent, children: [] },
      { path: 'journals', component: JournalsComponent, children: [] },
      { path: 'purge', component: PurgeComponent, children: [] },
      { path: 'groups', component: GroupsComponent, children: [] },
      { path: 'configs', component: ConfigurationComponent, children: [] },
      { path: 'applications', component: ApplicationsComponent, children: [] },
      { path: '', redirectTo: '/logged/admin/dashboard', pathMatch: 'prefix' }
    ]
  },
];

authguard.service(如果本地存储有令牌,canActivate returns true)

@Injectable()
export class AdminGuardService implements CanActivate, CanActivateChild, CanLoad {
  jwtHelper: JwtHelper = new JwtHelper();
  constructor(private router: Router, private alerter: AlertService) { }
  // tslint:disable-next-line:max-line-length
  canActivate(route?: ActivatedRouteSnapshot, state?: RouterStateSnapshot): boolean { return canActivate(route, state, this, [global.roles.admin]); }
  canActivateChild(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean { return this.canActivate(route, state); }
  canLoad(route: Route): boolean { console.log('coucou'); return canActivate(null, null, this, [global.roles.admin]); }
}

EDIT canActivate 函数,由警卫使用(适用于 canActivatecanActivateChild):

export function canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot, caller: any, userRoles: string[]): boolean {
  try {
    // Get the token
    let token = localStorage.getItem('jwt');

    // If no token found, not connected
    if (!token) {
      caller.alerter.error(`Vous n'êtes pas connecté`);
      caller.router.navigate(['/login']);
      return false;
    }

    // Try to get roles. If it fails, not a valid token.
    let decodedToken = caller.jwtHelper.decodeToken(token);
    let roles: Array<String> = decodedToken.roles.split(',');

    // return true if any role is found
    let found = false;
    for (let role of userRoles) {
      if (roles.indexOf(role) >= 0) { found = true; }
    }
    if (found) { return true; }

    // Role not found => Unauthorized
    caller.alerter.error(`Autorisation manquante`);
    caller.router.navigate(['/logged/main']);
    return false;

  } catch (ex) {
    // Catch the JWT errors
    caller.alerter.error(`La session utilisateur est corrompue`);
    caller.router.navigate(['/login']);
    return false;
  }
}

您的 canActivate 可能有问题。这是方法体:

return canActivate(route, state, this, [global.roles.admin]);

它正在调用另一个名为 canActivate 的函数。那是什么?

您不想在主 loggedRoutes const 中定义延迟加载模块的子路由。您应该只定义模块的入口点,然后让模块处理其内部路由。通过在 loggedRoutes 中定义模块的子路由,您实际上已经声明它们是根目录的一部分 应用程序模块。

canLoad 仅用于延迟加载的模块 - 并且这些模块必须控制自己的路由。根模块无法控制这一点,因为它会知道延迟加载模块的组件,并且它不会被延迟加载。

从您的 loggedRoutes 中删除此内容:

...adminRoutes,
...pilotageRoutes,
...suiviProdRoutes,

...mainRoutes 很好,因为它不是惰性加载模块的一部分。

并确保您的延迟加载模块已注册其路由:

@NgModule({
  imports: [ RouterModule.forChild(adminRoutes) ]
})
export class AdminModule { }

延迟加载的模块想要在内部处理它们自己的路由,因为你在顶层注册所有路由你的应用程序不关心延迟加载的模块,它会看到你的管理路由并将你导航到那里,因为这只是一条正常的路线。然而,AOT 编译器会看到你的 loadChildrens,它会为你分块你的代码,但是包含你的应用程序的主块也将包含所有应该延迟加载的额外模块。

您还应该从 adminRoutes:

中删除第一条路线的名称
path: 'admin', component: AdminComponent...

应该变成

path: '', component: AdminComponent...

路由段 admin 已经由您的模块提供,在主 loggedRoutes.

中注册为 admin