如何使用嵌套模块进行路由应该在Angular 2中工作?

时间:2016-09-21 20:32:29

标签: angular angular2-routing angular2-router3

我不能因为对饼干的喜爱而弄清楚如何配置Angular 2路由器的最新版本(最终版本中的那个)。我有一个相当大的Angular 2 RC5应用程序正在运行,但是在我继续前进之前需要迁移到最终版本。

在这个应用程序中,我有很多嵌套组件,根据Google的文档,应该将其组织为模块中的功能。我的应用中的典型网址如此

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

但也有其他一些,例如

user/34/settings

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

我已经阅读了相当长篇大论的文档,并不急于切入追逐,只是发现这个案例根本没有涉及。我无法相信这种情况不会起作用,这似乎是一个巨大的疏忽,所以我想问题是我还没有完全理解这个路由器实际上是如何工作的 - 我感觉我是我不是唯一一个。

我创建this plunker来说明我的观点。

在这个掠夺者中我得到了2级嵌套

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

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

benutzer/78/klient/56

即。路由器实际上找到该路由,此时它没有。

在我将代码移到plunker并添加dashboard.component之前(因为我无法轻松修改plunker中的URL,所以我不得不诉诸routerLink)我实际上可以导航到

klient/56

这不应该是可能的。似乎在另一个模块中定义的每个路由都被添加到根目录而不是彼此叠加。

非常感谢任何帮助。

2 个答案:

答案 0 :(得分: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懒惰地加载子模块。我说&#34;懒惰&#34;因为我无法弄清楚如何做到这一点,并且不确定是否有可能这样做。为了懒洋洋地加载孩子,我们可以做到

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 }
];

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

另请注意loadChildren。在上面的示例中,我使用app作为根。唯一的原因是我在当地环境中测试过。我不是普兰克的忠实粉丝。但是对于您的Plunker,您应该使用src作为根。

IMO,延迟加载看起来更干净,因为孩子不了解父母,但是强迫你懒洋洋地加载模块,这可能不是期望。但在某些情况下,需要这样做,因为它允许更轻的初始负载。

有关延迟加载的详细信息,请参阅Asynchronous Routing

上的文档路由部分

答案 1 :(得分:1)

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

复制我的答案

我也可以使用它,除非你真的需要渲染层次结构中的所有父组件,否则我认为我的解决方案更加优雅。

理解我的方法的关键是所有路由,无论嵌套在模块中的深度如何都添加到根模块。简单的例子,假设我们要使用此网址导航到DepartmentModuleEmployeeModule

/department/1/employee/2

此时我们会看到员工2的详细信息。在departmentdepartment.routing.tsemployee 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 }
    ]}
];

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

EmployeeModule

DepartmentModule将由export const employeeRoutes: Routes = [ { path: 'department/:id/employee', component: EmployeeComponent, children: [ { path: '', component: EmployeesComponent }, { path: ':id', component: EmployeeDetailsComponent } ]} ]; 导入。现在,就像我说的那样,不幸的是,这不起作用。

但是,只需进行一次更改即可:

DepartmentModule

问题是,employee导航到ActivatedRoute网址时,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']); } } 不再活跃,但您仍然可以访问lineinfile中的每个参数:

mount

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