【问题标题】:Nested outlets in master layout outlet in angular 6角度 6 的主布局插座中的嵌套插座
【发布时间】:2018-11-29 07:58:03
【问题描述】:

我正在构建一个 Angular 6 应用程序,其中有两个单独的屏幕:

  1. 登录(登录、注册、忘记密码、配置文件)
    • 这些页面不是布局的一部分
  2. 布局(仪表板、产品、发票)
    • 这些页面应该共享相同的布局

我的应用是基于模块的,所以我有

  • app.module.ts
  • account.module.ts
  • dashboard.module.ts
  • products.module.ts
  • invoices.module.ts

每个模块都有一个空组件,只包含一个出口,除了布局(包含页眉、正文和页脚)。

我想实现那些路线:

  • site.com/account/login
  • site.com |将导航到仪表板
    • site.com/dashboard
  • site.com/products
  • site.com/invoices

Visual explanation


我添加account.module没有问题,但是添加layout.module时不知道如何配置路由

注意:也许我的整个方法都是错误的,但对我来说这是唯一合乎逻辑的事情,因为我有包含组件的模块,我想为可能的延迟加载配置做好准备。

如果我走错了路,请给我建议。

代码

app.module.ts

import { BrowserModule } from '@angular/platform-browser';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { NgModule } from '@angular/core';
import { HttpClientModule } from '@angular/common/http';
import { RouterModule } from '@angular/router';

import { AppComponent } from './app.component';

import { LayoutModule } from './layout/layout.module';
import { AccountModule } from './feature-components/membership/account.module';


@NgModule({
  declarations: [
    AppComponent,
    FetchDataComponent
  ],
  imports: [
    BrowserModule.withServerTransition({ appId: 'ng-cli-universal' }),
    BrowserAnimationsModule,
    HttpClientModule,
    LayoutModule,
    AccountModule,
    BrowserAnimationsModule
    RouterModule.forRoot([
     { path: '', component: LayoutOutletComponent },
     { path: '**', component: PageNotFoundComponent }
    ]),
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

app.component.html

<router-outlet></router-outlet>

account.module.ts

import { NgModule } from '@angular/core';
import { SharedModule } from '@app-shared/shared.module';
import { LoginComponent } from './login/login.component';
import { ResetPasswordComponent } from './reset-password/reset-password.component';
import { ChangePasswordComponent } from './change-password/change-password.component';
import { RouterModule } from '@angular/router';
import { AccountOutletComponent } from './account-outlet/account-outlet.component';

@NgModule({
  imports: [
    SharedModule,
    RouterModule.forChild(
      [{
        path: 'account', component: AccountOutletComponent,
        children: [
          { path: 'login', component: LoginComponent },
          { path: 'reset-password', component: ResetPasswordComponent },
          { path: 'change-password', component: ChangePasswordComponent },
          { path: '', redirectTo: 'login', pathMatch: 'full' }
        ]
      }]
    )
  ],
  exports: [
    LoginComponent,
    ResetPasswordComponent,
    ChangePasswordComponent
  ],
  declarations: [
    AccountOutletComponent,
    LoginComponent,
    ResetPasswordComponent,
    ChangePasswordComponent
  ]
})
export class AccountModule { }

所以,这里没有问题,当我添加 layout module 时问题就开始了

import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { RouterModule } from '@angular/router';

import { NavMenuComponent } from './nav-menu/nav-menu.component';
import { FooterComponent } from './footer/footer.component';
import { LayoutOutletComponent  } from './layout-outlet/layout-outlet.component';
import { InvoicesModule } from '../feature-components/invoices/invoices.module';


@NgModule({
  imports: [
    CommonModule,
    InvoicesModule,
    RouterModule
  )],
  exports: [
    NavMenuComponent,
    FooterComponent
  ],
  declarations: [
    NavMenuComponent,
    FooterComponent,
    LayoutOutletComponent
  ]
})
export class LayoutModule { }

【问题讨论】:

    标签: angular typescript routing nested-routes


    【解决方案1】:

    你应该做以下事情

    • 在应用模块中创建路径以加载模块而不是组件
    • 在布局模块中创建路径以加载仪表板、产品和发票模块
    • 在布局组件中设置页眉路由器出口和页脚和/或其他布局元素
    • 在模块仪表板、产品和发票中设置加载组件的路径

    app.module

        RouterModule.forRoot([
          { path: '', loadChildren: '(PathToLayoutMoudle)#LayoutModule' },
          { path: '**', component: PageNotFoundComponent }
        ]),
    

    layout.module

        RouterModule.forChild([
          { path: '', component: LayoutComponent},
              children: [
              { path: 'dashboard',loadChildren: 
                  PathToDashboardMoudle)#DashboardMoudle'},
              { path: 'products',loadChildren: 
                  PathToProductsMoudle)#ProductsMoudle'},
              { path: 'invoices',loadChildren: 
                  PathToInvoicesMoudle)#InvoicesdMoudle'},
          ]
        ]),
    

    account.module

      RouterModule.forChild(
      [{
        path: '', component: AccountOutletComponent,
        children: [
          { path: 'login', component: LoginComponent },
          { path: 'reset-password', component: ResetPasswordComponent },
          { path: 'change-password', component: ChangePasswordComponent },
          { path: '', redirectTo: 'login', pathMatch: 'full' }
        ]
      }]
    

    【讨论】:

      【解决方案2】:

      我认为你走在正确的道路上。首先你需要处理急切的路由,然后你可以切换到惰性模块。

      你需要做什么:

      app.module.ts

      @NgModule({
        imports: [
          BrowserModule,
          AccountModule,
          LayoutModule,
          RouterModule.forRoot([
            { path: '**', component: PageNotFoundComponent }
          ])
        ],
        declarations: [
          AppComponent,
          PageNotFoundComponent
        ],
        bootstrap: [AppComponent]
      })
      export class AppModule { }
      

      layout.module.ts

      @NgModule({
        imports: [
          CommonModule,
          RouterModule.forChild([
            {
              path: '',
              component: LayoutOutletComponent,
              children: [
                {
                  path: 'dashboard',
                  loadChildren: () => DashboardModule
                },
                {
                  path: 'products',
                  loadChildren: () => ProductsModule
                },
                { path: '', redirectTo: '/dashboard', pathMatch: 'full' }
              ]
            }
          ])
        ],
        declarations: [
          LayoutOutletComponent
        ]
      })
      export class LayoutModule { }
      

      您需要知道的主要事情是所有角度路线都合并在一个路线配置中。要理解这一点,我建议您观看@deborahk 的great video

      你不能只写

      { path: '', component: LayoutOutletComponent},
      

      并单独导入其他模块(ProductsModuleDashboardModule)。嵌套路由应作为子路由提供。

      现在,当您配置好所有路由后,您可以轻松切换到延迟加载模块:

      {
        path: '',
          component: LayoutOutletComponent,
          children: [
            {
              path: 'dashboard',
              loadChildren: 'pathToModule#DashboardModule'
            },
            {
              path: 'products',
              loadChildren: 'pathToModule#ProductsModule'
            },
            { path: '', redirectTo: '/dashboard', pathMatch: 'full' }
          ]
      }
      

      你也可以在 AppModule 中延迟加载 LayoutModule

      @NgModule({ imports: [ ... LayoutModule, RouterModule.forRoot([ { path: '', loadChildren: './layout/layout.module#LayoutModule' }, { path: '**', component: PageNotFoundComponent } ]) ], ... }) export class AppModule { }

      我在 github 上创建了 ng-nested-outlets 应用程序,请尝试一下。

      您也可以通过 Stackblitz Demo

      在线试用

      另见

      【讨论】:

      • 如果您想增强我的回答,请使用编辑按钮。和我的基本一样。
      • @yt61 您在布局模块中的配置错误。 dashboard, products and invoices 应该是子路由,以便将这些组件放置在布局出口内
      • @yurzui,所以现在你只是懒加载整个LayoutModule,我们怎么能懒加载只是ProductsModule,而Dashboard要被热切加载?
      • @yurzui 太棒了!谢谢!有用。现在只有一件事..当我使用--prod发布项目时,当我有:`loadChildren:()=> DashboardModule`它在IIS上失败,抱怨:错误错误:未捕获(承诺):错误:运行时编译器未加载错误:运行时编译器未加载但如果我将其更改为: loadChildren: '(pathToDashModule)#DashboardModule' 它在 iis 上工作正常,但如果我这样做,我可以看到它已打开延迟加载- 我最初不想使用
      猜你喜欢
      • 2012-12-20
      • 2018-03-07
      • 2018-08-18
      • 2017-02-15
      • 1970-01-01
      • 1970-01-01
      • 2017-03-03
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多