嵌套路由结合懒加载模块时,如何动态设置路由outlet?
问题
我的应用包含多个可独立运行的模块,部分场景下需要在一个模块中展示另一模块的组件。比如模块1是「文件模块」,模块2是「文件夹模块」:文件夹可独立存在,当部分文件夹关联文件后,用户需要在不离开文件夹视图的情况下查看文件详情。
我已经实现了非懒加载模式下的该功能,但期望路由能动态构建并设置对应outlet名称。尝试懒加载模块时,无法根据路由层级为module2的路由设置对应outlet(例如此场景下需要设为outlet:'lvl2'),当前的路由配置如下:
// 预期的MODULE1_ROUTES const MODULE1_ROUTES = [ { path: '', component: ListComponent, loadChildren: () => import('./module1-detail-routing.module').then( (m) => m.Module1DetailRoutingModule ), }, ]; // module1-detail-routing.module中的配置 const MODULE1_DETAIL_ROUTES: Routes = [ { path: 'detail/:id', component: DetailComponent, outlet: 'lvl1', }, { path: 'module2', outlet: 'lvl1', loadChildren: () => import('../module2/module2-routing.module').then( (m) => m.Module2RoutingModule ), }, ];
请问如何在懒加载模块时修改路由,以动态设置其outlet?
解决方案
可以通过两种方式实现懒加载模块时动态设置outlet:
1. 在懒加载模块自身路由中直接指定outlet
不需要在父路由的loadChildren节点设置outlet,直接在懒加载模块的路由配置里定义outlet属性,这样模块的所有路由都会绑定到目标outlet:
修改module2-routing.module.ts的配置:
// module2-routing.module.ts const MODULE2_ROUTES: Routes = [ { path: '', // 对应父路由的path: 'module2' component: Module2ListComponent, outlet: 'lvl2' // 直接指定目标outlet }, // 模块2的其他子路由统一使用该outlet { path: 'detail/:id', component: Module2DetailComponent, outlet: 'lvl2' } ];
同时调整父路由配置,移除outlet: 'lvl1',让懒加载模块自行处理outlet绑定:
// module1-detail-routing.module.ts const MODULE1_DETAIL_ROUTES: Routes = [ { path: 'detail/:id', component: DetailComponent, outlet: 'lvl1', }, { path: 'module2', loadChildren: () => import('../module2/module2-routing.module').then( (m) => m.Module2RoutingModule ), }, ];
2. 用路由守卫动态修改路由配置
如果需要根据路由层级动态计算outlet名称,可在父模块的路由守卫中修改懒加载模块的路由配置:
- 创建路由守卫,在
canLoad钩子中动态为懒加载路由添加outlet属性:
import { Injectable } from '@angular/core'; import { CanLoad, Route, Router } from '@angular/router'; @Injectable({ providedIn: 'root' }) export class DynamicOutletGuard implements CanLoad { constructor(private router: Router) {} canLoad(route: Route): boolean { // 根据实际逻辑动态生成outlet名称 const targetOutlet = 'lvl2'; // 加载懒加载模块的路由配置并修改 route.loadChildren().then((module) => { const lazyRoutes = (module as any).MODULE2_ROUTES; // 为所有路由及子路由设置outlet const setOutlet = (routes: any[]) => { routes.forEach(r => { r.outlet = targetOutlet; if (r.children) setOutlet(r.children); }); }; setOutlet(lazyRoutes); // 更新全局路由配置 this.router.resetConfig([...this.router.config, ...lazyRoutes]); }); return true; } }
- 在父路由中添加该守卫:
// module1-detail-routing.module.ts const MODULE1_DETAIL_ROUTES: Routes = [ { path: 'detail/:id', component: DetailComponent, outlet: 'lvl1', }, { path: 'module2', canLoad: [DynamicOutletGuard], loadChildren: () => import('../module2/module2-routing.module').then( (m) => m.Module2RoutingModule ), }, ];
注意:这种方式需要确保懒加载模块的路由配置是可访问的静态变量,且router.resetConfig会重置全局路由,需避免覆盖原有配置。
内容的提问来源于stack exchange,提问作者Fernando Silva
相关产品推荐
相关产品推荐

