Angular中使用loadRemoteModule动态添加路由子项的实现问题
实现方案
原方案失效原因
- Resolve守卫执行时,路由的子路由匹配流程已完成,此时修改
routeConfig.children不会触发重新匹配,变更不生效 - 你的resolve函数没有返回符合要求的值,不符合Angular Resolver的语法要求
- 模板中使用了命名
router-outlet,但动态添加的子路由未指定outlet属性,路由无法匹配到对应出口
最优实现方案:直接在loadChildren中按需加载
不需要动态修改路由配置,直接在加载逻辑中根据路由参数判断返回对应微前端模块即可,代码更简洁稳定:
const routes: Routes = [ // 其他路由配置 { path: ':params', component: TestComponent, children: [ { path: '', loadChildren: () => { const activatedRoute = inject(ActivatedRoute); const moduleType = activatedRoute.snapshot.params['params']; if (moduleType === 'test1') { return loadRemoteModule({ remoteName: 'test1', remoteEntry: '/c/test1/remoteEntry.js', exposedModule: 'Test1Module', }).then(m => m.Test1Module) } else { return loadRemoteModule({ remoteName: 'test2', remoteEntry: '/c/test2/remoteEntry.js', exposedModule: 'Test2Module', }).then(m => m.Test2Module) } } } ] }, ]; @NgModule({ imports: [RouterModule.forChild(routes)], exports: [RouterModule] }) export class TestRoutingModule {}
模板简化,不需要多个命名出口,用默认出口即可:
<!-- 不需要多出口的情况下直接用默认router-outlet即可 --> <router-outlet></router-outlet>
如果确实需要用到命名出口,只需要在子路由配置中添加对应outlet字段:
{ path: '', outlet: 'test1', // 对应模板里的name属性 loadChildren: () => // 你的加载逻辑 }
如果你使用的是Angular 14以下版本,不支持在loadChildren回调中直接调用inject,优先使用下面的动态修改路由方案即可。
动态修改路由配置的兼容方案
如果业务场景必须动态修改路由,将原来的Resolver替换为CanActivate守卫,修改配置后手动触发一次重定向即可:
@Injectable() export class TestRouteGuard implements CanActivate { constructor(private router: Router) {} canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean | UrlTree { const moduleType = route.params['params']; // 先清空原有子路由 route.routeConfig.children = []; // 添加对应子路由 if (moduleType === 'test1') { route.routeConfig.children.push({ path: '', loadChildren: () => loadRemoteModule({ remoteName: 'test1', remoteEntry: '/c/test1/remoteEntry.js', exposedModule: 'Test1Module', }).then(m => m.Test1Module) }); } else { route.routeConfig.children.push({ path: '', loadChildren: () => loadRemoteModule({ remoteName: 'test2', remoteEntry: '/c/test2/remoteEntry.js', exposedModule: 'Test2Module', }).then(m => m.Test2Module) }); } // 用新的路由配置重新匹配当前地址,replaceUrl避免产生历史记录 return this.router.parseUrl(state.url); } }
在路由配置中替换resolve为canActivate:
{ path: ':params', component: TestComponent, canActivate: [TestRouteGuard], children: [] // 初始留空即可 }
内容的提问来源于stack exchange,提问作者emka26
相关产品推荐
相关产品推荐

