Angular 2(Final):resetConfig将路由添加到延迟加载的路由

Etc*_*lon 5 router module lazy-loading dynamic angular

我正在尝试了解如何动态地向从延迟加载的模块添加路由。我有核心应用,有路线:

export const routes = [{
    path: "",
    component: HomeComponent
}, {
    path: "moduleA",
    loadChildren: "app/moduleA/A.module"
}];
Run Code Online (Sandbox Code Playgroud)

在A.module中,我从“本地”模块A.routes.config.ts导入路由:

const routes = [{
    path: "",
    component: ModuleAHomeComponent,
    children: [
        { path: "", component: ModuleAListComponent },
        { path: ":id", component: ModuleADetailComponent }
    ]
}];
export const routing = RouterModule.forChild(routes);
Run Code Online (Sandbox Code Playgroud)

到目前为止,一切都很好。现在,在ModuleADetailComponent中,我有一个用于Web应用程序的“其他模块”列表,我将其称为插件,这些模块是单独开发的,我希望能够在ModuleADetailComponent页面中显示。因此,此组件的模板如下所示:

<div *ngFor="let plugin of plugins">
    <div class="header">{{ plugin.name }}</div>
    <router-outlet name="*plugin.name*">*LOAD MODULE HERE*</router-outlet>
</div>
Run Code Online (Sandbox Code Playgroud)

当然,插件是在导航到ModuleADetailComponent时加载的配置,因此我无法提前知道配置了哪些模块以及有多少个模块。最后,每个插件都可以是NgModule(在工作台环境中单独开发)。

我需要的是:如何动态修改路由器配置,以将子级添加到moduleA.routes.config.ts中定义的路由?例如,如果我有2个插件,我想动态地使用router.resetConfig来获得moduleA.routes.config.ts像这样的东西:

const routes = [{
    path: "",
    component: ModuleAHomeComponent,
    children: [
        { path: "", component: ModuleAListComponent },
        { 
            path: ":id",
            component: ModuleADetailComponent,
            children: [
                {
                    path: "plugin1",
                    loadChildren: "app/plugins/plugin1.module",
                    outlet: "plugin1"
                },
                {
                    path: "plugin2",
                    loadChildren: "app/plugins/plugin2.module",
                    outlet: "plugin2"
                }                
            ]
        }
    ]
}];
export const routing = RouterModule.forChild(routes);
Run Code Online (Sandbox Code Playgroud)

我希望我能实现它,否则插件将不得不在没有路由的情况下进行开发...但是它们可以成为大型子模块,而这将从导航中受益。

编辑27/09/2016:我已经组装了这个plunkr:http ://plnkr.co/edit/6aV5n5K5wdqdiYo49lZv 。我目前能够做的是动态加载组件并将其添加到应用程序中(请参见“动态模块”选项卡)。尽管没有找到任何官方文档,我仍然要做的是使用多个命名的路由器插座(请参见“动态路由”标签)。尽管具有标签名称,但路线是提前知道的。

我要做的是:动态加载配置(DynamicRoutesComponent中的dynamicRoutes数组),并且仅在为每条动态路由创建一个路由器出口并使用resetConfig(或它需要的东西)后才能具有此配置:

{
  path: "dynamic-routed",
  component: DynamicRoutesComponent,
  children: [
    { path: "", component: EmptyComponent },
    { path: "component1", component: Component1, outlet: "component1" },
    { path: "component2", component: Component2, outlet: "component2" }
  ]
}
Run Code Online (Sandbox Code Playgroud)

每个动态路线有一个孩子。

提前致谢!

Bur*_*sci 6

首先,loadChildren必须以以下格式提供属性方法(https://angular.io/docs/ts/latest/guide/router.html#!#asynchronous-routing):

{
  path: 'admin',
  loadChildren: 'app/admin/admin.module#AdminModule',
},
Run Code Online (Sandbox Code Playgroud)

如您在上方所见,the module path和the module name#char 结合在一起。

在您的情况下,您需要按以下方式或多或少地修改app.routes(不确定模块/文件名,而plunkr示例不能反映此问题中给出的名称):

export const routes = [{
    path: "",
    component: HomeComponent
}, {
    path: "moduleA",
    loadChildren: "app/moduleA#ModuleA"
}];
Run Code Online (Sandbox Code Playgroud)

这只是一个介绍,现在让我们继续解决您的问题。据我所读,您想动态添加子路由。

您可以使用以下代码在功能模块中动态提供子路线。

import {ROUTES} from '@angular/router/src/router_config_loader';
import {ANALYZE_FOR_ENTRY_COMPONENTS} from '@angular/core';

[...]
let routesToAdd = ... // provide your routes here

@NgModule({
  [...]
  imports: [RouterModule.forChild([])] // Empty on purpose
  [...]
  providers: [
    {
      provide: ROUTES,
      useValue: routesToAdd,
      multi: true
    },
    {
      provide: ANALYZE_FOR_ENTRY_COMPONENTS,
      useValue: routesToAdd, // provide them here too
      multi: true
    }
  ],
  [...]
})
Run Code Online (Sandbox Code Playgroud)

您必须为ANALYZE_FOR_ENTRY_COMPONENTS令牌(以及ROUTES令牌)提供相同的路由,否则会收到No component factory found for YOUR_COMPONENT. Did you add it to @NgModule.entryComponents?错误消息。

但是,此代码可能会在AoT编译期间产生错误。在这种情况下,您需要提供一个factory而不是valuefor ROUTES令牌。但是,您将无法提供factoryfor ANALYZE_FOR_ENTRY_COMPONENTS令牌-它仅接受useValue(请参阅https://github.com/angular/angular/blob/03e855ae8f9e9b86251320c7551a96092bd8b0c4/modules/%40angular/compiler/src/metadata_resolver.ts#L926)。

在这种情况下,请在功能模块上使用以下代码:

import {ROUTES} from '@angular/router/src/router_config_loader';

[...]
let routesToAdd = ... // provide your routes here

@NgModule({
  [...]
  imports: [RouterModule.forChild([])] // Empty on purpose
  [...]
  providers: [
    {
      provide: ROUTES,
      useFactory: (getRoutesFromSomewhere),
      //deps: [SomeService, SOME_TOKEN] // deps is optional, in the case you need no params - delete it; otherwise pass 'em
      multi: true
    }
  ],
  entryComponents: [CompA, CompB, CompC, etc...]
  [...]
})
Run Code Online (Sandbox Code Playgroud)

注意:使用Observables / Promises提供路由不是可靠的解决方案,因此Angular路由器期望Route[]Routes,但是HTTP请求只能返回一个Observable / Promise(Angular应用已初始化,但是路由的检索过程仍继续使用Observables / Promises)(请参阅https://github.com/ngx-i18n-router/config-loader#readme)。

使用返回Route[]或的函数Routes

同时,您可以检查@ ngx-i18n-router / core(用于Angular的国际化实用程序,得益于动态路由)的模块文件,并将本示例应用程序作为其用途。