Angular: 如何根据服务在同一路径上路由不同的模块
Angular: How to route different modules on the same path depending on service
假设一个服务 ABService
有一个方法 isAResponsible: () => boolean
和两个模块:AModule
和 BModule
。
问题是:是否可以根据isAResponsible
returns在AModule
和BModule
之间切换?如果 isAResponsible
的值发生变化,我们如何 'reroute' 并重新渲染? ABService
可能对其他服务有多种依赖性,因此最好以某种方式使用 DI 系统。
示例:
如果感兴趣的路线是 /aorb
和 ABService.isAResponsible
returns true
,那么我们想要路线 AModule
。如果 ABService.isAResponsible
returns false
但是我们希望 BModule
管理进一步的路由。请注意,一切都应该发生在 shared 路线上。
我用守卫和canActivate
/canLoad
试过了,但没有成功:
app.module.ts
import { NgModule } from '@angular/core';
import { RouterModule } from '@angular/router';
import { BrowserModule } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import { AorBActivateGuard } from './aorb-activate.guard';
import { ABService } from './ab.service';
@NgModule({
imports: [
BrowserModule,
RouterModule.forRoot([
{
path: 'aorb',
canActivate: [AorBActivateGuard],
loadChildren: () => import('./a/a.module').then((m) => m.AModule),
},
{
path: 'aorb',
loadChildren: () => import('./b/b.module').then((m) => m.BModule),
},
]),
],
providers: [AorBActivateGuard, ABService],
declarations: [AppComponent],
bootstrap: [AppComponent],
})
export class AppModule {}
ab.service.ts
import { Injectable } from '@angular/core';
@Injectable()
export class ABService {
private aIsResponsible = true;
constructor() {}
switch() {
this.aIsResponsible = !this.aIsResponsible;
}
isAResponsible() {
return this.aIsResponsible;
}
}
aorb-activate.guard.ts
import { Injectable } from '@angular/core';
import {
CanActivate,
ActivatedRouteSnapshot,
RouterStateSnapshot,
} from '@angular/router';
import { Observable } from 'rxjs';
import { ABService } from './ab.service';
@Injectable()
export class AorBActivateGuard implements CanActivate {
constructor(private abService: ABService) {}
canActivate(
next: ActivatedRouteSnapshot,
state: RouterStateSnapshot
): Observable<boolean> | Promise<boolean> | boolean {
return this.abService.isAResponsible();
}
}
你可以试试这个吗,我刚刚在本地检查过它是否有效,只要换一种方式思考,你就有了解决方案:)
import { NgModule } from '@angular/core';
import { RouterModule } from '@angular/router';
import { BrowserModule } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import { AorBActivateGuard } from './aorb-activate.guard';
import { ABService } from './ab.service';
@NgModule({
imports: [
BrowserModule,
RouterModule.forRoot([
{
path: 'aorb',
loadChildren: () => {
if ((new ABService()).isAResponsible()){
return import('./a/a.module').then((m) => m.AModule)
} else {
return import('./b/b.module').then((m) => m.BModule)
}
},
},
]),
],
providers: [AorBActivateGuard, ABService],
declarations: [AppComponent],
bootstrap: [AppComponent],
})
export class AppModule {}
可以在 AppModule
中注入 ABService
并监听来自 ABService
的变化。每次发生变化时,我们都可以重新配置(= 切换模块)路由器并让它导航相同的路由。这样我们总是加载负责的模块。
[...]
@NgModule({
imports: [
BrowserModule,
RouterModule.forRoot([], {
initialNavigation: 'disabled',
}),
],
providers: [ABService, BooleanStorageService],
declarations: [AppComponent],
bootstrap: [AppComponent],
})
export class AppModule {
constructor(private router: Router, private abService: ABService) {
abService.onABChange.subscribe(this.resetRouterConfig(true).bind(this));
this.resetRouterConfig(false)();
this.router.initialNavigation();
}
reloadCurrentRoute() {
const currentUrl = this.router.url;
this.router.navigateByUrl('/', { skipLocationChange: true }).then(() => {
this.router.navigate([currentUrl]);
});
}
resetRouterConfig(refresh: boolean) {
return () => {
const constructedConfig = [
{
path: '',
pathMatch: 'full',
redirectTo: 'aorb',
},
{
path: 'aorb',
loadChildren: () => {
if (this.abService.isAResponsible()) {
return import('./a/a.module').then((m) => m.AModule);
} else {
return import('./b/b.module').then((m) => m.BModule);
}
},
},
];
this.router.resetConfig(constructedConfig);
if (refresh) this.reloadCurrentRoute();
};
}
}
您可以找到一个工作示例 here。
假设一个服务 ABService
有一个方法 isAResponsible: () => boolean
和两个模块:AModule
和 BModule
。
问题是:是否可以根据isAResponsible
returns在AModule
和BModule
之间切换?如果 isAResponsible
的值发生变化,我们如何 'reroute' 并重新渲染? ABService
可能对其他服务有多种依赖性,因此最好以某种方式使用 DI 系统。
示例:
如果感兴趣的路线是 /aorb
和 ABService.isAResponsible
returns true
,那么我们想要路线 AModule
。如果 ABService.isAResponsible
returns false
但是我们希望 BModule
管理进一步的路由。请注意,一切都应该发生在 shared 路线上。
我用守卫和canActivate
/canLoad
试过了,但没有成功:
app.module.ts
import { NgModule } from '@angular/core';
import { RouterModule } from '@angular/router';
import { BrowserModule } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import { AorBActivateGuard } from './aorb-activate.guard';
import { ABService } from './ab.service';
@NgModule({
imports: [
BrowserModule,
RouterModule.forRoot([
{
path: 'aorb',
canActivate: [AorBActivateGuard],
loadChildren: () => import('./a/a.module').then((m) => m.AModule),
},
{
path: 'aorb',
loadChildren: () => import('./b/b.module').then((m) => m.BModule),
},
]),
],
providers: [AorBActivateGuard, ABService],
declarations: [AppComponent],
bootstrap: [AppComponent],
})
export class AppModule {}
ab.service.ts
import { Injectable } from '@angular/core';
@Injectable()
export class ABService {
private aIsResponsible = true;
constructor() {}
switch() {
this.aIsResponsible = !this.aIsResponsible;
}
isAResponsible() {
return this.aIsResponsible;
}
}
aorb-activate.guard.ts
import { Injectable } from '@angular/core';
import {
CanActivate,
ActivatedRouteSnapshot,
RouterStateSnapshot,
} from '@angular/router';
import { Observable } from 'rxjs';
import { ABService } from './ab.service';
@Injectable()
export class AorBActivateGuard implements CanActivate {
constructor(private abService: ABService) {}
canActivate(
next: ActivatedRouteSnapshot,
state: RouterStateSnapshot
): Observable<boolean> | Promise<boolean> | boolean {
return this.abService.isAResponsible();
}
}
你可以试试这个吗,我刚刚在本地检查过它是否有效,只要换一种方式思考,你就有了解决方案:)
import { NgModule } from '@angular/core';
import { RouterModule } from '@angular/router';
import { BrowserModule } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import { AorBActivateGuard } from './aorb-activate.guard';
import { ABService } from './ab.service';
@NgModule({
imports: [
BrowserModule,
RouterModule.forRoot([
{
path: 'aorb',
loadChildren: () => {
if ((new ABService()).isAResponsible()){
return import('./a/a.module').then((m) => m.AModule)
} else {
return import('./b/b.module').then((m) => m.BModule)
}
},
},
]),
],
providers: [AorBActivateGuard, ABService],
declarations: [AppComponent],
bootstrap: [AppComponent],
})
export class AppModule {}
可以在 AppModule
中注入 ABService
并监听来自 ABService
的变化。每次发生变化时,我们都可以重新配置(= 切换模块)路由器并让它导航相同的路由。这样我们总是加载负责的模块。
[...]
@NgModule({
imports: [
BrowserModule,
RouterModule.forRoot([], {
initialNavigation: 'disabled',
}),
],
providers: [ABService, BooleanStorageService],
declarations: [AppComponent],
bootstrap: [AppComponent],
})
export class AppModule {
constructor(private router: Router, private abService: ABService) {
abService.onABChange.subscribe(this.resetRouterConfig(true).bind(this));
this.resetRouterConfig(false)();
this.router.initialNavigation();
}
reloadCurrentRoute() {
const currentUrl = this.router.url;
this.router.navigateByUrl('/', { skipLocationChange: true }).then(() => {
this.router.navigate([currentUrl]);
});
}
resetRouterConfig(refresh: boolean) {
return () => {
const constructedConfig = [
{
path: '',
pathMatch: 'full',
redirectTo: 'aorb',
},
{
path: 'aorb',
loadChildren: () => {
if (this.abService.isAResponsible()) {
return import('./a/a.module').then((m) => m.AModule);
} else {
return import('./b/b.module').then((m) => m.BModule);
}
},
},
];
this.router.resetConfig(constructedConfig);
if (refresh) this.reloadCurrentRoute();
};
}
}
您可以找到一个工作示例 here。