根据条件具有相同 url 的多条路线
multiple routes with same url based on condition
我们有一个 angular 应用程序,其中外部部分供外部用户使用,内部部分供内部用户使用。
我们希望它们具有相同的 url 和不同的组件(内部组件与外部组件完全不同)。
Angular 可以吗?如果我使用守卫,它不会比第一条路线走得更远。如果使用匹配器,它不适用于嵌套路由...
这是一些所需的伪代码:
const appRoutes: Routes = [
// internal zone
{ path = '', children: internRoutes, [condition checking something on global service] },
// external zone
{ path = '', children: externRoutes, [condition checking something on global service] }
];
我们找到了解决方案。
在我们的应用程序路由模块中,我们只分配一个空数组 (forRoot),因为整个应用程序分为外部和内部。
@NgModule({
imports: [
// by default we have no routes
// the app component will inject the routes based on I or E (same URL different modules/components)
RouterModule.forRoot([], { enableTracing: true })
],
...
})
在我们的应用程序组件中,我们根据条件(内部或外部)添加具有不同子路由的路由。
constructor(private router: Router, private state: State, ...) {
// here we add the routes which is different based on zone (dynamic routes)
this.router.config.unshift(
{
path: '',
children: this.state.zone == 'I' ? internRoutes : externRoutes
}
);
您可以使用一个模块来处理应该加载的模块,方法是使用 Angular 的 useFactory 提供程序提供 RouterModule 的 ROUTES。
代码可能是这样的。
// HandlerModule
@NgModule({
declarations: [],
imports: [
CommonModule,
RouterModule
],
providers: [
{
provide: ROUTES,
useFactory: configHandlerRoutes,
deps: [SessionService],
multi: true
}
]
})
export class HandlerModule {}
export function configHandlerRoutes(sessionService: SessionService) {
let routes: Routes = [];
if (sessionService.isLoggedIn()) {
routes = [
{
path: '', loadChildren: () => import('app/member/member.module').then(mod => mod.MemberModule)
}
];
} else {
routes = [
{
path: '', loadChildren: () => import(app/guest/guest.module).then(mod => mod.GuestModule)
}
];
}
return routes;
}
然后在您的 AppRoutingModule 中,路径 '' 的模块将成为 HandlerModule:
// AppRoutingModule
{
path: '',
loadChildren: () => import('app/handler/handler.module').then(mod => mod.HandlerModule)
}
在 SessionService 之后,当提供方法 isLoggedIn 的值发生变化时,您必须更新 Router.config,因为应用程序只会加载第一次加载的页面(模块)。这是因为 HandlerModule 中的 useFactory 提供程序使用的函数“configHandlerRoutes”仅在我们第一次导航到“”路径时执行,之后 Angular 路由器已经知道他必须加载哪个模块。
总而言之,在 SessionService 中你必须做的事情:
export class SessionService {
private loggedIn: boolean;
constructor(private router: Router) {
this.loggedIn = false;
}
public isLoggedIn(): boolean {
return this.loggedIn;
}
public setLoggedIn(value: boolean): void {
const previous = this.loggedIn;
this.loggedIn = value;
if (previous === this.loggedIn) {
return;
}
const i = this.router.config.findIndex(x => x.path === '');
this.router.config.splice(i, 1);
this.router.config.push(
{path: '', loadChildren: () => import('app/handler/handler.module').then(mod => mod.HandlerModule)}
);
}
}
就是这样。
如果你想要另一个参考,这里有一篇文章,他们使用相同的方法:https://medium.com/@german.quinteros/angular-use-the-same-route-path-for-different-modules-or-components-11db75cac455
我们有一个 angular 应用程序,其中外部部分供外部用户使用,内部部分供内部用户使用。
我们希望它们具有相同的 url 和不同的组件(内部组件与外部组件完全不同)。
Angular 可以吗?如果我使用守卫,它不会比第一条路线走得更远。如果使用匹配器,它不适用于嵌套路由...
这是一些所需的伪代码:
const appRoutes: Routes = [
// internal zone
{ path = '', children: internRoutes, [condition checking something on global service] },
// external zone
{ path = '', children: externRoutes, [condition checking something on global service] }
];
我们找到了解决方案。
在我们的应用程序路由模块中,我们只分配一个空数组 (forRoot),因为整个应用程序分为外部和内部。
@NgModule({
imports: [
// by default we have no routes
// the app component will inject the routes based on I or E (same URL different modules/components)
RouterModule.forRoot([], { enableTracing: true })
],
...
})
在我们的应用程序组件中,我们根据条件(内部或外部)添加具有不同子路由的路由。
constructor(private router: Router, private state: State, ...) {
// here we add the routes which is different based on zone (dynamic routes)
this.router.config.unshift(
{
path: '',
children: this.state.zone == 'I' ? internRoutes : externRoutes
}
);
您可以使用一个模块来处理应该加载的模块,方法是使用 Angular 的 useFactory 提供程序提供 RouterModule 的 ROUTES。
代码可能是这样的。
// HandlerModule
@NgModule({
declarations: [],
imports: [
CommonModule,
RouterModule
],
providers: [
{
provide: ROUTES,
useFactory: configHandlerRoutes,
deps: [SessionService],
multi: true
}
]
})
export class HandlerModule {}
export function configHandlerRoutes(sessionService: SessionService) {
let routes: Routes = [];
if (sessionService.isLoggedIn()) {
routes = [
{
path: '', loadChildren: () => import('app/member/member.module').then(mod => mod.MemberModule)
}
];
} else {
routes = [
{
path: '', loadChildren: () => import(app/guest/guest.module).then(mod => mod.GuestModule)
}
];
}
return routes;
}
然后在您的 AppRoutingModule 中,路径 '' 的模块将成为 HandlerModule:
// AppRoutingModule
{
path: '',
loadChildren: () => import('app/handler/handler.module').then(mod => mod.HandlerModule)
}
在 SessionService 之后,当提供方法 isLoggedIn 的值发生变化时,您必须更新 Router.config,因为应用程序只会加载第一次加载的页面(模块)。这是因为 HandlerModule 中的 useFactory 提供程序使用的函数“configHandlerRoutes”仅在我们第一次导航到“”路径时执行,之后 Angular 路由器已经知道他必须加载哪个模块。
总而言之,在 SessionService 中你必须做的事情:
export class SessionService {
private loggedIn: boolean;
constructor(private router: Router) {
this.loggedIn = false;
}
public isLoggedIn(): boolean {
return this.loggedIn;
}
public setLoggedIn(value: boolean): void {
const previous = this.loggedIn;
this.loggedIn = value;
if (previous === this.loggedIn) {
return;
}
const i = this.router.config.findIndex(x => x.path === '');
this.router.config.splice(i, 1);
this.router.config.push(
{path: '', loadChildren: () => import('app/handler/handler.module').then(mod => mod.HandlerModule)}
);
}
}
就是这样。
如果你想要另一个参考,这里有一篇文章,他们使用相同的方法:https://medium.com/@german.quinteros/angular-use-the-same-route-path-for-different-modules-or-components-11db75cac455