Angular:如何根据服务在同一路径上路由不同模块

Szy*_*mon 5 routes module angular

ABService想象一个具有方法isAResponsible: () => boolean和两个模块的服务:AModuleBModule​​ 。

问题是:是否可以根据返回值在AModule和之间进行切换?如果值发生变化,我们如何“重新路由”和重新渲染?可能对其他服务有多种依赖关系,因此最好以某种方式使用 DI 系统。BModuleisAResponsibleisAResponsibleABService

示例:如果感兴趣的路线是/aorbABService.isAResponsible返回true,那么我们希望路线AModule。然而,如果ABService.isAResponsible返回,false我们希望BModule管理进一步的路由。请注意,一切都应该发生在共享路线上。

我尝试与守卫和canActivate/canLoad但没有成功:

应用程序模块.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 {}
Run Code Online (Sandbox Code Playgroud)

ab服务.ts

import { Injectable } from '@angular/core';

@Injectable()
export class ABService {
  private aIsResponsible = true;

  constructor() {}

  switch() {
    this.aIsResponsible = !this.aIsResponsible;
  }

  isAResponsible() {
    return this.aIsResponsible;
  }
}
Run Code Online (Sandbox Code Playgroud)

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();
  }
}
Run Code Online (Sandbox Code Playgroud)

Szy*_*mon 0

人们可以注入ABServiceAppModule监听来自 的变化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();
    };
  }
}
Run Code Online (Sandbox Code Playgroud)

您可以在这里找到一个工作示例。