如何作为模块的子模块路由到模块 - Angular 2 RC 5
How to route to a Module as a child of a Module - Angular 2 RC 5
我正在将我正在开发的应用程序升级到最新的 Angular 2 候选版本。作为这项工作的一部分,我尝试使用 NgModule 规范并将我的应用程序的所有部分迁移到模块。在大多数情况下,除了路由问题外,一切进展顺利。
"@angular/common": "2.0.0-rc.5",
"@angular/compiler": "2.0.0-rc.5",
"@angular/core": "2.0.0-rc.5",
"@angular/forms": "0.3.0",
"@angular/http": "2.0.0-rc.5",
"@angular/platform-browser": "2.0.0-rc.5",
"@angular/platform-browser-dynamic": "2.0.0-rc.5",
"@angular/router": "3.0.0-rc.1",
我的应用程序构建为多个模块的组合,多个模块作为父模块的子模块粘合在一起。例如,我有一个管理模块,它由一个通知模块、一个用户模块和一个电话模块(例如)组成。这些模块的路由应该看起来像...
/admin/notifications/my-notifications
/admin/users/new-user
/admin/telephony/whatever
在较早版本的路由器中,使用 "children"
很容易实现这一点
export const AdminRoutes: RouterConfig = [
{
path: "Admin",
component: AdminComponent,
Children: [
...UserRoutes,
...TelephonyRoutes,
...NotificationRoutes
]
}
]
在另一个文件中,作为子模块的一部分,我还将定义各个模块路由,即
export const UserRoutes: RouterConfig = [
{
path: "users",
component: userComponent,
children: [
{path: "new-user", component: newUserComponent}
]
}
]
这一切都非常有效。在升级到模块的过程中,我把所有东西都移到了它们自己的路由文件中,所以现在这两个看起来更像这样
const AdminRoutes: Routes = [
{path: "admin", component: AdminComponent}
]
export const adminRouting = RouterModule.forChild(AdminRoutes)
和
const UserRoutes: Routes = [
path: "users",
component: userComponent,
children: [
{path: "new-user", component: newUserComponent}
]
]
export const userRouting = RouterModule.forChild(UserRoutes)
所有这些都准备就绪后,我有一个导入 userRouting 的 UsersModule,然后是一个导入 adminRoutes 和 UsersModule 的 AdminModule。我的想法是,由于 UsersModule 是 AdminModule 的子项,因此路由会像以前一样工作。不幸的是,事实并非如此,所以我最终得到的用户路由只是
/users/new-user
而不是
/admin/users/new-user
此外,因此,新用户组件不会加载到我的管理组件的路由器出口中,这会影响我的应用程序的样式和导航。
我一辈子都想不出如何将我的 UserModule 的路由引用为我的 AdminModule 的子级。我试过用旧方法做这件事,但得到关于两个模块中的路由的错误。显然,由于这是新发布的,因此围绕其中一些案例的文档有点有限。
任何人都可以提供任何帮助,我们将不胜感激!
好的,在周末的大部分时间里摆弄这个之后,我最终得到了它 运行。最终对我有用的是执行以下操作:
- 为您要路由的每个模块导出全部
Routes
。不要在子模块中导入任何 RouterModule.forChild()
。
- 导出子模块定义中子路由定义可见的每个组件。
- 像往常一样导入(意味着 Typescript
import
关键字)所有子路由,并使用 ...
运算符将它们合并到正确的路径下。我无法让它与定义路径的子模块一起工作,但在父模块上工作正常(并且与延迟加载兼容)。
在我的例子中,我在这样的层次结构中有三个级别:
- 根 (
/
)
- 编辑器(
editor/:projectId
)
- 查询(
query/:queryId
)
- 页数(
page/:pageId
)
- 前面(
about
)
以下定义适用于 /editor/:projectId/query/:queryId
路径:
// app.routes.ts
import {editorRoutes} from './editor/editor.routes'
// Relevant excerpt how to load those routes, notice that the "editor/:projectId"
// part is defined on the parent
{
path: '',
children: [
{
path: 'editor/:projectId',
children: [...editorRoutes]
//loadChildren: '/app/editor/editor.module'
},
]
}
编辑器路由如下所示:
// app/editor/editor.routes.ts
import {queryEditorRoutes} from './query/query-editor.routes'
import {pageEditorRoutes} from './page/page-editor.routes'
{
path: "", // Path is defined in parent
component : EditorComponent,
children : [
{
path: 'query',
children: [...queryEditorRoutes]
//loadChildren: '/app/editor/query/query-editor.module'
},
{
path: 'page',
children: [...pageEditorRoutes]
//loadChildren: '/app/editor/page/page-editor.module'
}
]
}
查询编辑器的最后部分如下所示:
// app/editor/query/query-editor.routes.ts
{
path: "",
component : QueryEditorHostComponent,
children : [
{ path: 'create', component : QueryCreateComponent },
{ path: ':queryId', component : QueryEditorComponent }
]
}
但是,要使这个工作,一般Editor
需要导入和导出QueryEditor
和QueryEditor
需要导出QueryCreateComponent
和 QueryEditorComponent
因为它们在导入时可见。如果不这样做,您将得到类似 Component XYZ is defined in multiple modules
.
的错误
请注意,延迟加载也适用于此设置,在这种情况下,当然不应导入子路由。
我也找到了解决这个问题的方法。基本上,我按照以前的方式定义我的路线,但这次是在顶级子级别。例如我的管理员路线:
const AdminRoutes: Routes = [
{
path: 'admin',
component: AdminComponent,
children: [
...setupRoutes
]
}
]
export const adminRouting = RouterModule.forChild(AdminRoutes)
我的设置路由文件是从一个子区域导入的,它定义了它自己的路由,包括更多的子区域。问题在于此文件导出 "Routes" 对象而不是 RouterModule.forChild 结果。
设置完成后,我从子模块定义中删除了子路由和子路由。然后我不得不从每个子模块导出路由中使用的所有组件,就像上面提到的 Marcus 一样。一旦我这样做了,路线就开始像我希望的那样工作了。
我不认为我真的喜欢这个解决方案,因为我的父模块对子模块路由了解得太多了。但至少它是一种绕过 RC5 的简单方法,而且它不会到处泄漏我的所有组件。我将继续并将 Marcus 的回答标记为答案,因为他让我走上了正确的轨道。
当您使用 ngModules 和 RC5 时,parent 模块的路由配置不需要了解 child 模块路由的任何信息。您只需在此处为 parent 模块定义路由。
此外,您必须将 child 模块导入到 parent 模块中。
在 child 模块中,你必须这样定义你的路由:
export const childRoutes: Routes = [
{
path: 'someChild',
component: SomeChildComponent,
children: [
{ path: '', component: SomeChildSubComponent1 },
{ path: 'comp1', component: SomeChildSubComponent1 },
{ path: 'comp2', component: SomeChildSubComponent2 }
]
}
];
这会让你有一个像 /someParent/someChild/comp1 一样的 url - 组件显示在它们对应的 router-outlet 中。
请注意:您必须声明空路径的组件。否则你无法导航到你 children.
我也让这个工作正常,除非你真的需要渲染层次结构中的所有父组件,否则我认为我的解决方案要优雅得多。
理解我的方法的关键是所有路由,无论嵌套在模块中有多深,都被添加到根模块中。快速示例,假设我们有一个 DepartmentModule
和一个 EmployeeModule
,我们想使用此 URL
导航到它们
/department/1/employee/2
此时我们将看到员工 2 的详细信息。为 department.routing.ts
中的 department
和 employee.routing.ts
中的 employee
配置路由 不会 按我们预期的方式工作,您会注意到可以导航到
/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 }
]}
];
要注意的是,当您导航到 employee
URL 时,DepartmentModule
不再积极参与,但您仍然可以访问 [=] 中的每个参数26=]:
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 团队进行下一次重大更改。
我遇到了同样的问题。
这里的答案使用 loadChildren 非常好:
{
path: 'mypath',
loadChildren : () => myModule
}
我认为 2.0.0 rc5 现在不感兴趣。不过是在Angular4工作的,可能也太早了。
@NgModule({
imports: [
RouterModule.forRoot([
{path: "", redirectTo: "test-sample", pathMatch: "full"},
{
path: "test-sample",
loadChildren: () => TestSampleModule
}
])
],
exports: [RouterModule],
declarations: []
})
export class AppRoutingModule{}
@NgModule({
imports: [
RouterModule.forChild([{
path: "",
component: TestSampleComponent,
children: [
{path: "", redirectTo: "home", pathMatch: "full"},
{
path: "home",
loadChildren: () => HomeModule
},
{
path: "about",
loadChildren: () => AboutModule
}
]
}
])
],
exports: [RouterModule],
declarations: []
})
export class TestSampleRoutingModule {}
@NgModule({
imports: [RouterModule.forChild([{
path: "",
component: AboutComponent
}
])],
exports: [RouterModule]
})
export class AboutRoutingModule {}
考虑 loadChildren: () => {...}
。这不是延迟加载。
使用loadChildren
。没关系。但是当你重新启动构建过程时,你会得到构建错误。您应该将导出的符号与 loadChildren
.
相匹配
import { ChildModule } from './child/child.module';
export function childRouteFactory() {
return ChildModule;
}
...
{
path: 'child',
loadChildren: childRouteFactory
}
...
我正在将我正在开发的应用程序升级到最新的 Angular 2 候选版本。作为这项工作的一部分,我尝试使用 NgModule 规范并将我的应用程序的所有部分迁移到模块。在大多数情况下,除了路由问题外,一切进展顺利。
"@angular/common": "2.0.0-rc.5",
"@angular/compiler": "2.0.0-rc.5",
"@angular/core": "2.0.0-rc.5",
"@angular/forms": "0.3.0",
"@angular/http": "2.0.0-rc.5",
"@angular/platform-browser": "2.0.0-rc.5",
"@angular/platform-browser-dynamic": "2.0.0-rc.5",
"@angular/router": "3.0.0-rc.1",
我的应用程序构建为多个模块的组合,多个模块作为父模块的子模块粘合在一起。例如,我有一个管理模块,它由一个通知模块、一个用户模块和一个电话模块(例如)组成。这些模块的路由应该看起来像...
/admin/notifications/my-notifications
/admin/users/new-user
/admin/telephony/whatever
在较早版本的路由器中,使用 "children"
很容易实现这一点export const AdminRoutes: RouterConfig = [
{
path: "Admin",
component: AdminComponent,
Children: [
...UserRoutes,
...TelephonyRoutes,
...NotificationRoutes
]
}
]
在另一个文件中,作为子模块的一部分,我还将定义各个模块路由,即
export const UserRoutes: RouterConfig = [
{
path: "users",
component: userComponent,
children: [
{path: "new-user", component: newUserComponent}
]
}
]
这一切都非常有效。在升级到模块的过程中,我把所有东西都移到了它们自己的路由文件中,所以现在这两个看起来更像这样
const AdminRoutes: Routes = [
{path: "admin", component: AdminComponent}
]
export const adminRouting = RouterModule.forChild(AdminRoutes)
和
const UserRoutes: Routes = [
path: "users",
component: userComponent,
children: [
{path: "new-user", component: newUserComponent}
]
]
export const userRouting = RouterModule.forChild(UserRoutes)
所有这些都准备就绪后,我有一个导入 userRouting 的 UsersModule,然后是一个导入 adminRoutes 和 UsersModule 的 AdminModule。我的想法是,由于 UsersModule 是 AdminModule 的子项,因此路由会像以前一样工作。不幸的是,事实并非如此,所以我最终得到的用户路由只是
/users/new-user
而不是
/admin/users/new-user
此外,因此,新用户组件不会加载到我的管理组件的路由器出口中,这会影响我的应用程序的样式和导航。
我一辈子都想不出如何将我的 UserModule 的路由引用为我的 AdminModule 的子级。我试过用旧方法做这件事,但得到关于两个模块中的路由的错误。显然,由于这是新发布的,因此围绕其中一些案例的文档有点有限。
任何人都可以提供任何帮助,我们将不胜感激!
好的,在周末的大部分时间里摆弄这个之后,我最终得到了它 运行。最终对我有用的是执行以下操作:
- 为您要路由的每个模块导出全部
Routes
。不要在子模块中导入任何RouterModule.forChild()
。 - 导出子模块定义中子路由定义可见的每个组件。
- 像往常一样导入(意味着 Typescript
import
关键字)所有子路由,并使用...
运算符将它们合并到正确的路径下。我无法让它与定义路径的子模块一起工作,但在父模块上工作正常(并且与延迟加载兼容)。
在我的例子中,我在这样的层次结构中有三个级别:
- 根 (
/
)- 编辑器(
editor/:projectId
)- 查询(
query/:queryId
) - 页数(
page/:pageId
)
- 查询(
- 前面(
about
)
- 编辑器(
以下定义适用于 /editor/:projectId/query/:queryId
路径:
// app.routes.ts
import {editorRoutes} from './editor/editor.routes'
// Relevant excerpt how to load those routes, notice that the "editor/:projectId"
// part is defined on the parent
{
path: '',
children: [
{
path: 'editor/:projectId',
children: [...editorRoutes]
//loadChildren: '/app/editor/editor.module'
},
]
}
编辑器路由如下所示:
// app/editor/editor.routes.ts
import {queryEditorRoutes} from './query/query-editor.routes'
import {pageEditorRoutes} from './page/page-editor.routes'
{
path: "", // Path is defined in parent
component : EditorComponent,
children : [
{
path: 'query',
children: [...queryEditorRoutes]
//loadChildren: '/app/editor/query/query-editor.module'
},
{
path: 'page',
children: [...pageEditorRoutes]
//loadChildren: '/app/editor/page/page-editor.module'
}
]
}
查询编辑器的最后部分如下所示:
// app/editor/query/query-editor.routes.ts
{
path: "",
component : QueryEditorHostComponent,
children : [
{ path: 'create', component : QueryCreateComponent },
{ path: ':queryId', component : QueryEditorComponent }
]
}
但是,要使这个工作,一般Editor
需要导入和导出QueryEditor
和QueryEditor
需要导出QueryCreateComponent
和 QueryEditorComponent
因为它们在导入时可见。如果不这样做,您将得到类似 Component XYZ is defined in multiple modules
.
请注意,延迟加载也适用于此设置,在这种情况下,当然不应导入子路由。
我也找到了解决这个问题的方法。基本上,我按照以前的方式定义我的路线,但这次是在顶级子级别。例如我的管理员路线:
const AdminRoutes: Routes = [
{
path: 'admin',
component: AdminComponent,
children: [
...setupRoutes
]
}
]
export const adminRouting = RouterModule.forChild(AdminRoutes)
我的设置路由文件是从一个子区域导入的,它定义了它自己的路由,包括更多的子区域。问题在于此文件导出 "Routes" 对象而不是 RouterModule.forChild 结果。
设置完成后,我从子模块定义中删除了子路由和子路由。然后我不得不从每个子模块导出路由中使用的所有组件,就像上面提到的 Marcus 一样。一旦我这样做了,路线就开始像我希望的那样工作了。
我不认为我真的喜欢这个解决方案,因为我的父模块对子模块路由了解得太多了。但至少它是一种绕过 RC5 的简单方法,而且它不会到处泄漏我的所有组件。我将继续并将 Marcus 的回答标记为答案,因为他让我走上了正确的轨道。
当您使用 ngModules 和 RC5 时,parent 模块的路由配置不需要了解 child 模块路由的任何信息。您只需在此处为 parent 模块定义路由。 此外,您必须将 child 模块导入到 parent 模块中。 在 child 模块中,你必须这样定义你的路由:
export const childRoutes: Routes = [
{
path: 'someChild',
component: SomeChildComponent,
children: [
{ path: '', component: SomeChildSubComponent1 },
{ path: 'comp1', component: SomeChildSubComponent1 },
{ path: 'comp2', component: SomeChildSubComponent2 }
]
}
];
这会让你有一个像 /someParent/someChild/comp1 一样的 url - 组件显示在它们对应的 router-outlet 中。 请注意:您必须声明空路径的组件。否则你无法导航到你 children.
我也让这个工作正常,除非你真的需要渲染层次结构中的所有父组件,否则我认为我的解决方案要优雅得多。
理解我的方法的关键是所有路由,无论嵌套在模块中有多深,都被添加到根模块中。快速示例,假设我们有一个 DepartmentModule
和一个 EmployeeModule
,我们想使用此 URL
/department/1/employee/2
此时我们将看到员工 2 的详细信息。为 department.routing.ts
中的 department
和 employee.routing.ts
中的 employee
配置路由 不会 按我们预期的方式工作,您会注意到可以导航到
/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 }
]}
];
要注意的是,当您导航到 employee
URL 时,DepartmentModule
不再积极参与,但您仍然可以访问 [=] 中的每个参数26=]:
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 团队进行下一次重大更改。
我遇到了同样的问题。
这里的答案使用 loadChildren 非常好:
{
path: 'mypath',
loadChildren : () => myModule
}
我认为 2.0.0 rc5 现在不感兴趣。不过是在Angular4工作的,可能也太早了。
@NgModule({
imports: [
RouterModule.forRoot([
{path: "", redirectTo: "test-sample", pathMatch: "full"},
{
path: "test-sample",
loadChildren: () => TestSampleModule
}
])
],
exports: [RouterModule],
declarations: []
})
export class AppRoutingModule{}
@NgModule({
imports: [
RouterModule.forChild([{
path: "",
component: TestSampleComponent,
children: [
{path: "", redirectTo: "home", pathMatch: "full"},
{
path: "home",
loadChildren: () => HomeModule
},
{
path: "about",
loadChildren: () => AboutModule
}
]
}
])
],
exports: [RouterModule],
declarations: []
})
export class TestSampleRoutingModule {}
@NgModule({
imports: [RouterModule.forChild([{
path: "",
component: AboutComponent
}
])],
exports: [RouterModule]
})
export class AboutRoutingModule {}
考虑 loadChildren: () => {...}
。这不是延迟加载。
使用loadChildren
。没关系。但是当你重新启动构建过程时,你会得到构建错误。您应该将导出的符号与 loadChildren
.
import { ChildModule } from './child/child.module';
export function childRouteFactory() {
return ChildModule;
}
...
{
path: 'child',
loadChildren: childRouteFactory
}
...