如何作为模块的子模块路由到模块 - 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需要导入导出QueryEditorQueryEditor需要导出QueryCreateComponentQueryEditorComponent 因为它们在导入时可见。如果不这样做,您将得到类似 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 中的 departmentemployee.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
          }

https://github.com/angular/angular/issues/10958

我认为 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: () => {...}。这不是延迟加载。

详见feat: Support NgModules hierarchy sans Lazy Loading

使用loadChildren。没关系。但是当你重新启动构建过程时,你会得到构建错误。您应该将导出的符号与 loadChildren.

相匹配
import { ChildModule } from './child/child.module';

export function childRouteFactory() {
  return ChildModule;
}

...
  {
    path: 'child',
    loadChildren: childRouteFactory
  }
...