2

出于对 cookie 的喜爱,我无法弄清楚如何配置 Angular 2 路由器的最新版本(最终版本中的那个)。我有一个相当大的 Angular 2 RC5 应用程序启动并运行,但现在需要迁移到最终版本才能继续。

在这个应用程序中,我有很多嵌套组件,根据 Google 的文档,它们应该被组织为模块中的功能。我的应用程序中的典型 URL 如下所示

user/34/section/95/client/13/<feature>

但也有一些其他的,例如

user/34/settings

所以在这种情况下,settings将是一个功能模块。

我已经阅读了文档,这些文档相当冗长,并不急于切入正题,只是发现根本没有涵盖这个案例。我不敢相信这种情况行不通,这似乎是一个巨大的疏忽,所以我想问题是我还没有完全掌握这个路由器的实际工作原理——我有一种感觉,我米不是唯一的。

我创建了这个 plunker来说明我的观点。

在这个 plunker 中,我有 2 层嵌套

app -> benutzer (user) -> klient (client)

足以使问题出现。预期的结果是我可以导航到

benutzer/78/klient/56

即路由器实际上找到了该路由,而目前它没有。

在我将代码移动到 plunker 并添加之前dashboard.component(因为我不能轻易修改 plunker 中的 URL,所以我不得不求助于routerLink)我实际上可以导航到

klient/56

这是不可能的。似乎在另一个模块中定义的每条路由都被添加到根目录,而不是在彼此之上构建。

对此的任何帮助将不胜感激。

4

2 回答 2

9

看看你所有的路线。

appRoutes = [      // AppModule
  { path: '', redirectTo: 'dashaboard' },
  { path: 'dashboard', component: DashboardComponent
];
benutzerRoutes = [ // BenutzerModule
  { path: 'benutzer/:id', component BenutzerComponent }
];
klientRoutes = [   // KlinetModule
  { path: 'klient/:id', component: KlientComponent }
]

导入模块的方式对构建路由的方式没有任何影响。它们是如何构建的只是基于我们如何构建。您对此有何期待

AppModule
   imports -> BenutzerModule
                   imports -> KlinetModule

通往以下路线

dashboard/benutzer/:id/klient/:id

事实并非如此。这些路由数组中的每一个都只是简单地添加到根。这就是为什么您可以访问klient/:id而不是dashboard/benutzer/:id.

我已经阅读了几次完整的路由文档,并且没有任何不同模块中嵌套路由的示例。所有示例都有从根路由加载的模块,就像您的示例一样,或者嵌套路由是同一路由配置的一部分。因此,由于没有示例,我想我们只需要使用我们所知道的并自己决定什么是最好的方法。

我能想到几种方法。第一个,最明显但 IMO 比下一个选项更具侵入性,就是将完整路线添加到路径

appRoutes = [      // AppModule
  { path: '', redirectTo: 'dashaboard' },
  { path: 'dashboard', component: DashboardComponent
];
benutzerRoutes = [ // BenutzerModule
  { path: 'dashboard/benutzer/:id', component BenutzerComponent }
];
klientRoutes = [   // KlinetModule
  { path: 'dashboard/benutzer/:id/klient/:id', component: KlientComponent }
]

我说这个选项更具侵入性,因为它迫使孩子们了解父母。在 Angular 2 架构中,这与我们构建组件的方式背道而驰。父母应该了解孩子,但不一定相反。

我能想到的另一个选择是用于loadChildren延迟加载子模块。我说“懒惰”是因为我不知道如何急切地做到这一点,甚至不确定是否有可能这样做。懒惰地加载孩子,我们可以做

export const appRoutes: Routes = [
  { path: '', redirectTo: 'dashboard', pathMatch: 'full' },
  { path: 'dashboard', component: DashboardComponent },
  {
    path: 'dashboard/benutzer',
    loadChildren: 'app/benutzer/benutzer.module#BenutzerModule'
  },
  { path: '**', component: NotFoundComponent }
];
export const benutzerRoutes: Routes = [
  { path: ':id', component: BenutzerComponent },
  {
    path: ':id/klient',
    loadChildren: 'app/klienten/klienten.module#KlientenModule'
  }
];
export const klientenRoutes: Routes = [
  { path: ':id', component: KlientComponent }
];

在这种情况下,我们将从其 parent 中删除所有子模块导入@NgModule。这允许延迟加载模块。如果我们离开,那么模块将在启动时急切地加载,但没有达到预期的效果(因此我说我不是如何急切地这样做)。

还要注意loadChildren. 在上面的示例中,我app用作根。唯一的原因是我在本地环境中测试过。我不是 Plunker 的忠实粉丝。但是,对于您的 Plunker,您应该使用srcroot。

IMO,延迟加载看起来更干净,因为孩子不知道父级,但这会迫使您延迟加载模块,这可能是不希望的。但在某些情况下,这是需要的,因为它允许更轻的初始负载。

有关延迟加载的更多信息,请参阅异步路由的文档路由部分

于 2016-09-22T04:24:40.883 回答
1

找到了一个可能的解决方案,从https://stackoverflow.com/a/39629949/370935复制我的答案

我也让它工作,除非你真的需要渲染层次结构中的所有父组件,否则我认为我的解决方案要优雅得多。

理解我的方法的关键是,所有路由,无论在模块中嵌套的深度如何,都被添加到根模块中。简单的例子,假设我们有一个DepartmentModule和一个EmployeeModule我们想使用这个 URL 导航到的

/department/1/employee/2

此时我们会看到员工 2 的详细信息。department为indepartment.routing.tsemployeein配置路线employee.routing.ts不会按我们预期的方式工作,您会注意到您可以导航到

/employee/2

从根组件,而

/department/1/employee/2

将崩溃(找不到路线)。此场景中的典型路由配置如下所示:

export const departmentRoutes: Routes = [
    { path: 'department', component: DepartmentComponent, children: [
        { path: '', component: DepartmentsComponent },
        { path: ':id', component: DepartmentDetailsComponent }
    ]}
];

export const employeeRoutes: Routes = [
    { path: 'employee', component: EmployeeComponent, children: [
        { path: '', component: EmployeesComponent },
        { path: ':id', component: EmployeeDetailsComponent }
    ]}
];

并将EmployeeModuleDepartmentModule. 现在,就像我说的那样,不幸的是,这不起作用。

但是,只需进行一次更改,它将:

export const employeeRoutes: Routes = [
    { path: 'department/:id/employee', component: EmployeeComponent, children: [
        { path: '', component: EmployeesComponent },
        { path: ':id', component: EmployeeDetailsComponent }
    ]}
];

问题是,一旦您导航到URL,DepartmentModule它就不再活跃,但您仍然可以从以下位置访问每个参数:employeeActivatedRoute

export class EmployeeDetailsComponent {
    departmentId: number;
    employeeId: number;
    constructor(route: ActivatedRoute) {
        route.parent.params.subscribe(params =>
            this.departmentId= +params['id'])
        route.params.subscribe(params => 
            this.employeeId= +params['id']);
    }
}

我想知道这是否应该是官方方法,但现在这对我有用,直到 Angular 2 团队的下一个重大变化。

于 2016-09-22T04:00:00.697 回答