Angular基于服务值动态loadChildren的实现及循环依赖问题
Angular动态配置loadChildren路由及循环依赖问题解决
循环依赖问题根源
你的代码出现循环依赖,是因为InjectedService和Router形成了闭环:ROUTES工厂依赖InjectedService,而Router本身依赖ROUTES,如果InjectedService又间接依赖了Router(或其依赖的服务依赖Router),就会触发这个报错。
问题1:能否不直接使用服务中的条件为路由提供判断依据?
可以,有几种可行方案:
- 用APP_INITIALIZER提前加载条件:在应用初始化时调用
InjectedService获取条件,把值存在全局变量或无依赖的独立服务里,路由工厂直接读取预加载的值,避免直接依赖InjectedService。
示例代码:// 全局变量或独立服务 export let layoutCondition: boolean; // APP_INITIALIZER提供者(放在AppModule或AppRouting的providers里) { provide: APP_INITIALIZER, useFactory: (service: InjectedService) => () => { // 假设getCondition是获取条件的异步方法 return service.getCondition().then(res => { layoutCondition = res; }); }, deps: [InjectedService], multi: true } // 修改后的路由工厂 const routesFactory = () => { return [ { path: "", runGuardsAndResolvers: "always", canActivate: [ApplicationStateGuard], canActivateChild: [ApplicationStateGuard], loadChildren: (): Promise<LayoutModuleV1 | LayoutModuleV2> => layoutCondition ? import(/* webpackChunkName: "layout-v1" */ "@app/layout-v1").then((mod) => mod.LayoutModuleV1) : import(/* webpackChunkName: "layout-v2" */ "@app/layout-v2").then((mod) => mod.LayoutModuleV2), }, ] } - 用路由守卫动态重定向:先定义一个空的父路由,在守卫里根据
InjectedService的条件重定向到对应版本的路由,路由配置里分开定义v1和v2的独立路由,避免在loadChildren里直接依赖服务。 - 存储到本地存储:如果条件是初始化时就能确定的(比如从后端接口获取后),可以把值存在
localStorage里,路由工厂直接读取localStorage的值,完全脱离服务依赖。
问题2:能否仅在ROUTES多提供者中设置动态loadChildren,其余路由放在RouterModule.forRoot中?
完全可以。Angular会自动合并RouterModule.forRoot里的静态路由和ROUTES多提供者提供的动态路由,最终形成完整的路由表。
调整后的代码示例:
// 静态路由(不需要动态配置的路由) const staticRoutes = [ { path: 'login', component: LoginComponent }, { path: '404', component: NotFoundComponent }, // 其他静态路由... ]; @NgModule({ exports: [RouterModule], // 静态路由放在forRoot里 imports: [RouterModule.forRoot(staticRoutes, { onSameUrlNavigation: "reload", relativeLinkResolution: "legacy" })], }) export class AppRouting { static forRoot(): ModuleWithProviders<AppRouting> { return { ngModule: AppRouting, providers: [ Service, { provide: ROUTES, useFactory: routesFactory, // 这里只提供需要动态配置的路由 deps: [InjectedService], multi: true } ] } } }
内容的提问来源于stack exchange,提问作者frankfullstack
相关产品推荐
相关产品推荐

