【问题标题】:Angular 5: conditional module lazy loadingAngular 5:条件模块延迟加载
【发布时间】:2018-03-21 11:34:30
【问题描述】:

我在尝试根据用户配置文件延迟加载模块时遇到问题, 我定义了三个默认路径(每个路由的路径为空),每个用户都可以访问一个特定的模块, 我正在使用警卫来确定当前的用户配置文件(实际上我正在手动切换以通过设置 const canGo =true 来设置默认加载的模块)

预期的行为是实际路由配置应该根据配置文件激活足够的路由,但事实并非如此。

export const routes: Routes = [
  {
    path: '',
    loadChildren: 'app/user/user.module#UserModule',
    canActivate: [
      CanActivateUserModuleGuard
    ],
  },
  {
    path: '',
    loadChildren: 'app/admin/admin.module#AdminModule',
    canActivate: [
      CanActivateAdminModuleGuard
    ]
  },
  {
    path: '',
    loadChildren: 'app/moderator/moderator.module#ModeratorModule',
    canActivate: [
      CanActivateModeratorModuleGuard
    ]
  },
  {
    path: '404',
    component: NotFoundComponent
  }
];

注意: 如果有兴趣,请在在线问题下方 https://stackblitz.com/edit/angular-vd4oyu?file=app%2Fapp-routing.module.ts

实现此要求的最佳方法是什么?

【问题讨论】:

  • 如果有错误,能否贴出错误堆栈?
  • 没有错误,但是这里的问题是路由检测默认降落到第一条路由路径,并且不会通过警卫继续到下一条路由。在提供的示例中,它应该重定向到管理模块。

标签: angular angular-cli


【解决方案1】:

路由器只会在它匹配的第一条路由上尝试防护。由于此限制,您将不得不尝试以下两个选项之一。

首先是实现一个自定义的UrlMatcher,它可以有效地完成你的守卫工作,然后只让它匹配你想要加载的模块。如果您需要使用其他服务,这可能会很困难,因为 UrlMatcher 只是一个函数,因此您不会获得任何 DI。

第二个选项是使用路径'' 的通用路由,上面有另一个守卫,执行其他三个守卫的操作,然后路由到适当的模块。这听起来有点像 hack,但是,Angular documentation 建议在 ToH 教程中这样做。

Demo

守卫

export class CanActivateModuleGuard implements CanActivate {

  constructor(private router: Router,
    private userGuard: CanActivateUserModuleGuard,
    private adminGuard: CanActivateAdminModuleGuard,
    private modGuard: CanActivateModeratorModuleGuard) { }

  canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean {
    let canGo = [{
      guard: this.adminGuard,
      url: 'admin',
    }, {
      guard: this.userGuard,
      url: 'user',
    }, {
      guard: this.modGuard,
      url: 'moderator',
    }].some((config) => {
      if (config.guard.canActivate(route, state)) {
        if (state.url !== `/${config.url}`) {
          this.router.navigate([config.url]);
        }
        return true;
      }
    });

    if (!canGo) {
      this.router.navigate(['/404']);
    }

    return canGo;
  }
}

路线

export const routes: Routes = [
  {
    path: '',
    canActivate: [CanActivateModuleGuard],
    children: [{
      path: 'user',
      loadChildren: 'app/user/user.module#UserModule',
      canActivate: [
        CanActivateUserModuleGuard
      ],
    },
    {
      path: 'admin',
      loadChildren: 'app/admin/admin.module#AdminModule',
      canActivate: [
        CanActivateAdminModuleGuard
      ]
    },
    {
      path: 'moderator',
      loadChildren: 'app/moderator/moderator.module#ModeratorModule',
      canActivate: [
        CanActivateModeratorModuleGuard
      ]
    }],
  },
  {
    path: '404',
    component: NotFoundComponent
  }
];

【讨论】:

  • 谢谢@Teddy Sterne,是否可以使用空 url 定义路由,这样我就不会破坏每个模块本地路由中的路由配置。
  • 带有模块的路由应该能够相对于模块的根目录,因此它们不需要知道它们是否在/admin/user/moderator 中。示例<a [routerLink]="./sub/route">Link</a>
【解决方案2】:

您也可以通过使用 routeFactory 来实现这一点。

因此您可以在单个路由上加载不同的模块,而无需创建额外的路由和守卫。

以下示例根据可注入服务提供的权限为路由 /parent 加载不同的模块。

app-routing.module.ts:

[
  { path: 'parent', loadChildren: () => 
    import('./parent/parent.module').then((m) => 
    m.ParentModule) },
  ...
]

parent-routing.module.ts:

function routesFactory(permissionService: PermissioService) {
  return [
  {
    path: '',
    loadChildren: () => {
      if (permissionService.role1) {
        return import('../module1/module1.module').then((m) => m.Module1Module);
      } else if (permissionService.role2) {
        return import('../module2/module2.module').then((m) => m.Module2Module);
      } 
    }
  }];
}

@NgModule({
  imports: [RouterModule.forChild([])],
  exports: [RouterModule],
  providers: [
  {
    provide: ROUTES,
    useFactory: routesFactory,
    multi: true,
    deps: [PermissioService]
  }
  ]
})
export class ParentRoutingModule { }

【讨论】:

    猜你喜欢
    • 2018-07-03
    • 2017-02-22
    • 1970-01-01
    • 2019-01-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多