首页 文章

如何作为模块的子项路由到模块 - Angular 2 RC 5

提问于
浏览
59

我正在将正在处理的应用程序升级到最新的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的孩子 . 我已经尝试过这种方式,并且在两个模块中获得有关路由的错误 . 显然,由于这是新发布的,其中一些案例的文档有点受限 .

任何人都可以提供任何帮助将不胜感激!

7 回答

  • 1

    好吧,在周末的大部分时间里摆弄这个后,我得到它在我的结束 . 最终对我有用的是做以下事情:

    • 为要路由的每个模块导出所有 Routes . 不要导入子模块中的任何 RouterModule.forChild() .

    • 从子模块定义中导出子路径定义中可见的每个组件 .

    • 像往常一样导入(意味着Typescript import 关键字)所有子路由,并使用 ... 运算符在正确的路径下合并它们 . 我无法使用定义路径的子模块,但在父模块上工作正常(并且与延迟加载兼容) .

    就我而言,我在层次结构中有三个级别,如下所示:

    • Root( /

    • 编辑( 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'
            }
        ]
    }
    

    QueryEditor的最后一部分如下所示:

    // app/editor/query/query-editor.routes.ts
    {
        path: "",
        component : QueryEditorHostComponent,
        children : [
            { path: 'create', component : QueryCreateComponent },
            { path: ':queryId', component : QueryEditorComponent }
        ]
    }
    

    但是,为了使这项工作,一般 Editor 需要导入 and 导出 QueryEditorQueryEditor 需要导出 QueryCreateComponentQueryEditorComponent ,因为这些导入可见 . 如果不这样做,将会出现 Component XYZ is defined in multiple modules 的错误 .

    请注意,延迟加载也适用于此设置,在这种情况下,当然不应导入子路由 .

  • 0

    我有同样的问题 .

    这里的答案非常好,使用loadChildren:

    {
                 path: 'mypath',
                 loadChildren : () => myModule
              }
    

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

  • 0

    我找到了解决这个问题的方法 . 基本上,我按照以前的方式定义我的路线,但这次是在最高的孩子级别 . 例如我的管理路线:

    const AdminRoutes: Routes = [
       {
          path: 'admin',
          component: AdminComponent,
          children: [
              ...setupRoutes
          ]
       }
    ]
    
    export const adminRouting = RouterModule.forChild(AdminRoutes)
    

    我的设置路由文件是从子区域导入的,该子区域定义了自己的路由,包括更多子项 . 问题是该文件导出“Routes”对象而不是RouterModule.forChild结果 .

    在设置之后,我从子模块定义中删除了子路径和子子路径 . 然后,我必须从每个子模块中导出路径中使用的所有组件,就像上面提到的Marcus一样 . 一旦我这样做了,路线开始工作就像我想要的那样 .

    我不认为我真的喜欢这个解决方案,因为我的父模块对子模块路由了解太多 . 但至少它是一种简单的方法来解决RC5,而事实并非如此我把所有组件泄漏到了整个地方 . 我会继续把马库斯的答案标记为答案,因为他让我走上正轨 .

  • 47

    我认为2.0.0 rc5现在不感兴趣了 . 但是在Angular 4中工作,也可能是早期 .

    @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

  • 0

    使用ngModules和RC5时,父模块的路由配置不需要了解子模块路由的任何信息 . 您只需在此处定义父模块的路由 . 此外,您必须将子模块导入父模块 . 在子模块中,您必须以这种方式定义路由:

    export const childRoutes: Routes = [
      {
        path: 'someChild',
          component: SomeChildComponent,
          children: [
            { path: '', component: SomeChildSubComponent1 },
            { path: 'comp1', component: SomeChildSubComponent1 },
            { path: 'comp2', component: SomeChildSubComponent2 }
          ]
      }
    ];
    

    这将让你有一个像/ someParent / someChild / comp1的网址 - 组件显示在相应的路由器插座中 . 请注意:您必须为空路径去除组件 . 否则你无法导航到你的孩子 .

  • 1

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

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

    /department/1/employee/2
    

    那时我们'd see employee 2'的详细信息 . 在 department.routing.tsdepartment.routing.tsemployee 中配置 department 的路由将无法按照我们的预期运行,您会发现可以导航到

    /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 不再处于活动状态,但您仍然可以访问 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']);
        }
    }
    

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

  • 28

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

    import { ChildModule } from './child/child.module';
    
    export function childRouteFactory() {
      return ChildModule;
    }
    
    ...
      {
        path: 'child',
        loadChildren: childRouteFactory
      }
    ...
    

相关问题