angular - 从服务动态确定 loadChildren 模块类型

标签 angular

在 Angular 应用程序中,我想确定要为指定路径加载哪个模块。这与延迟加载无关。这是关于动态路由配置/确定。

我有一个有 3 种访问权限的应用程序。每个访问都在他自己的模块中。在应用程序加载时,我想确定要加载的模块。在根路由级别和子级别。

在我看来,Angular 在很多方面都非常灵活,但路由配置非常静态......

例子:

// routed module
const routes: Routes = [
  { path: '', loadChildren: () => getModuleType() }
];

@NgModule({
  imports: [RouterModule.forChild(routes)],
  exports: [RouterModule]
})
class ParentModule {}

// My problem is there, where can i put this function ???
getModuleType() {

  // How can I have the dependecy injected ???
  return someApiService.getProfile().map(profile => {

    if (profile === 'A') {
      return ProfileAModule;
    }

    if (profile === 'B') {
      return ProfileBModule;
    }

  });
}

// some feature module
@NgModule({})
class ProfileAModule {}

@NgModule({})
class ProfileBModule {}

最佳答案

我会使用 protected 功能模块来实现这一点。

Feature X 文件夹和包含防护的 Core 文件夹的文件夹结构示例(如果需要,您可以拥有 N 个功能):

/core
    /guard
        / feature-x.guard.ts
/feature-x
    /feature-x.router.ts
    /feature-x.module.ts
    /feature-x.component.ts
    /feature-x-home
         /feature-x-home.module.ts
         /feature-x-home.router.ts
         /feature-x-home.component.ts
         /feature-x-home.component.html
         /feature-x-home.component.scss
    /feature-x-route1
         /feature-x-route1.module.ts
         /feature-x-route1.router.ts
         /feature-x-route1.component.ts
         /feature-x-route1.component.html
         /feature-x-route1.component.scss

特征 X

每个要素都包含其受限路线。 feature-x.router.ts会是这样的:
const featureXRoutes: Route[] = [
  {
    path: '',
    component: RouteXFeatureComponent,
    canActivate: [ FeatureXGuard ],
    children: [
      { path: '', redirectTo: '/feature-x-home', pathMatch: 'full' },
      { path: 'feature-x-home', loadChildren: '@app/feature-x/feature-x-home/feature-x-home.module#FeatureXHomeModule' },
      { path: 'feature-x-route-1', loadChildren: '@app/feature-x/feature-x-route-1/feature-x-route-1.module#FeatureXRoute1Module' },
      // ... etc
    ]
  }
];

export const FeatureXRoutingModule: ModuleWithProviders = RouterModule.forChild(featureXRoutes);

@app 是源路径文件夹的别名。如果您没有,请改用相对路径。延迟加载是可选的,但我强烈建议使用它。
feature-x-home.router.ts :
const featureXHomeRoutes: Route[] = [{
    path: '',
    component: FeatureXHomeComponent
}];

export const featureXHomeRoutes: ModuleWithProviders = RouterModule.forChild(featureXHomeRoutes);
feature-x.module.ts :
@NgModule({
  imports: [
    FeatureXRoutingModule
  ],
  declarations: [
    FeatureXComponent
  ]
})
export class FeatureXModule {}
feature-x.component.ts :
@Component({
  selector: 'app-feature-x',
  template: '<router-outlet></router-outlet>',
  styleUrls: [ './feature-x.component.scss' ]
})
export class FeatureXComponent {}

您可以提供与当前功能相关的任何布局。

主模块
app.module.ts :
@NgModule({
  imports: [
    CoreModule, // contains all guards declaration

    Feature1Module, // feature-x with x = 1
    Feature2Module, 
    Feature3Module,
    //... etc
    FeatureNModule,

    AppRoutingModule
  ],
  declarations: [
    AppComponent
  ],
  bootstrap: [ AppComponent ]

})
export class AppModule {}

如果你没有 CoreModule,那么在这里用 providers 声明所有的守卫属性(property)。
app.router.ts :
const appRoutes: Route[] = [
  { path: '', redirectTo: '/defaultRoute', pathMatch: 'full' },
  { path: '**', redirectTo: '/defaultRoute' }
];

export const AppRoutingModule: ModuleWithProviders = RouterModule.forRoot(appRoutes);
feature-x.module.ts :
const FEATURE_X = 'YOUR_FEATURE_X';
@Injectable()
export class FeatureXGuard implements CanActivate {
  constructor(
    private profilService: ProfilService,
    private router: Router
  ) {}

  canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean {
    const canGo = this.profileService.hasProfil(FEATURE_X);

    if (!canGo) {
      this._router.navigate([ this.profileService.getDefaultRouteFor(FEATURE_X) ]);
    }

    return canGo;
  }
}

有了这个系统,根据他的个人资料,用户将被重定向到正确的“主页”页面。如果他试图访问一个他没有正确个人资料的页面,他将被重定向到他的“主页”页面

更新

您需要根据您的用户配置文件使用 APP_BOOTSTRAP_LISTENER Hook 来注册应用程序路由。

https://stackblitz.com/edit/angular-vjfne6

关于angular - 从服务动态确定 loadChildren 模块类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48768053/

相关文章:

组件模板中的 Angular 2 路由器导出

Angular 2 - 无法设置表单数组值

javascript - 如何在我的 Angular Web 应用程序中导入或使用外部 JS 文件和函数

Angular - "has no exported member ' 可观察'”

angular - 从 Angular 2 中的另一个模块导出服务

typescript - 带有 tsconfig.json 的 Visual Studio 2015、Typescript 和 angular2

angular - Angular2 中的更改不会更新 View

javascript - Angular 2 document.removeEventListener 在类里面不起作用

node.js - 异常 : Token must be defined

javascript - 如何在 ionic 3 中将视频文件从 ios 转换为 base64