Angular 9 嵌套延迟加载模块,带有嵌套路由器出口

Posted

技术标签:

【中文标题】Angular 9 嵌套延迟加载模块,带有嵌套路由器出口【英文标题】:angular 9 nested lazy loaded modules with nested router outlets 【发布时间】:2020-10-01 17:11:56 【问题描述】:

我正在尝试使用 Angular 9 开发 SPA,我几乎尝试延迟加载每个组件及其所有子组件。当我尝试在一个延迟加载的组件中使用路由器插座并且我希望此路由器插座用于加载子组件(这也是延迟加载的)时,我的问题出现了。 当我这样做时,我总是将所有嵌套的延迟加载组件加载到 app.component.html 的主路由器插座中,而不是嵌套延迟加载组件中的路由器插座

app.component 模板:

<app-navbar></app-navbar>
<router-outlet></router-outlet>

app-routing.module:

const routes: Routes = [
   path: '', component: HomeComponent ,
   path: 'login', component: LoginComponent ,
   path: 'articles', loadChildren: () => import('./articles-viewer/articles-viewer.module').then(m => m.ArticlesViewerModule) ,
   path: 'dashboard', loadChildren: () => import('./dashboard/dashboard.module').then(m => m.DashboardModule) ,
   path: '**', redirectTo: ''
];

@NgModule(
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule]
)
export class AppRoutingModule  

app.module:

@NgModule(
  declarations: [
    AppComponent,
    HomeComponent,
    LoginComponent,
    NavbarComponent,
  ],
  imports: [
    BrowserModule,
    AppRoutingModule,
    HttpClientModule,
    BrowserAnimationsModule,
    AppAngularMaterial
  ],
  providers: [
    AppHttpInterceptors
  ],
  bootstrap: [AppComponent]
)
export class AppModule  

navbar.component 模板:

<a routerLink="">Home</a>
<a routerLink="/articles">Articles</a>
<a routerLink="/dashboard">Dashboard</a>

仪表板模板:

<a routerLink="statistics">Statistics</a>
<router-outlet></router-outlet>

dashboard.module:

@NgModule(
  declarations: [DashboardComponent],
  imports: [
    CommonModule,
    DashboardRoutingModule,
    AppAngularMaterial
  ]
)
export class DashboardModule  

dashboard-routing.module:

const routes: Routes = [
   path: '', component: DashboardComponent ,
   path: 'statistics', loadChildren: () => import('./statistics/statistics.module').then(m => m.StatisticsModule) 
  ];

@NgModule(
  imports: [RouterModule.forChild(routes)],
  exports: [RouterModule]
)
export class DashboardRoutingModule  

简而言之,统计组件(一个延迟加载的组件)被加载到 app.component 模板中声明的 router-outlet 中,而不是仪表板模板中的 router-outlet 中,并且仪表板组件被卸载

我试图在 angular.io 中找到解决方案,但我得到的只是在同一个组件中管理多个插座。另外,这是我在谷歌上搜索这个问题时得到的。

有什么解决办法吗?

【问题讨论】:

【参考方案1】:

我遇到了类似的问题!我这边的问题是我导入了延迟加载的模块,因此路由定义对于应用程序路由器出口是可见的。

如果您需要示例,请随时发表评论。

更新:2021-08-24 添加了完整代码示例

下面的例子可以无限扩展:

文件夹结构:

1 应用程序模块:

import  NgModule  from "@angular/core";
import  BrowserModule  from "@angular/platform-browser";

import  CoreModule  from "@core/core.module";
import  AppRoutingModule  from "@routes/app-routing.module";

import  AppComponent  from "./app.component";

import  BrowserAnimationsModule  from '@angular/platform-browser/animations';

@NgModule(
  declarations: [AppComponent],
  imports: [BrowserModule, CoreModule, AppRoutingModule, BrowserAnimationsModule],
  providers: [],
  bootstrap: [AppComponent],
)
export class AppModule 

2 应用程序组件:

import  Component  from "@angular/core";

@Component(
  selector: "rot-root",
  template: ` <router-outlet></router-outlet> `, // <===== ROOT ROUTER-OUTLET
  styleUrls: ["./app.component.scss"],
)
export class AppComponent 

3 app-routing.module:

import  NgModule  from "@angular/core";
import  Routes, RouterModule  from "@angular/router";

export const ROUTES: Routes = [
  
    path: "",
    pathMatch: "prefix",
    loadChildren: () =>
      import("./main/main-routing.module").then((m) => m.MainRoutingModule),
  ,
];

@NgModule(
  declarations: [],
  imports: [
    RouterModule.forRoot(ROUTES,  enableTracing: false )
  ],
  exports: [RouterModule],
)
export class AppRoutingModule 

4 main-routing.module:

import  NgModule  from "@angular/core";
import  Routes, RouterModule  from "@angular/router";

import  layoutModules  from "./layouts";

import  MainLayoutViewComponent  from "./layouts/main-layout/views";

export const SUBROUTES: Routes = [
  
    path: "",
    pathMatch: "prefix",
    component: MainLayoutViewComponent, // <==== DISPLAYED IN ROOT ROUTER-OUTLET
    children: [ // <==== CHILDREN ARE DISPLAYED IN SUB ROUTER-OUTLET (6)
      
        path: "dashboard",
        loadChildren: () => import("./dashboard/dashboard.module").then(m => m.DashboardModule)
      ,
      // <==== A LOT OF ROUTES FROM THE MAIN FOLDER - SAME AS DASHBOARD ====>
    ],
  ,
];

@NgModule(
  declarations: [],
  imports: [
    RouterModule.forChild(SUBROUTES),
    ...layoutModules
  ],
  exports: [RouterModule],
)
export class MainRoutingModule 

5 main-layout.module:

import  NgModule  from "@angular/core";
import  SharedModule  from "@shared/shared.module";

// material modules
// <==== a lot of material imports :D ====>

// module components
import  views  from "./views"; // <===== HERE I IMPORT THE MAIN-LAYOUT-VIEW
import  containers  from "./containers";
import  components  from "./components";

@NgModule(
  declarations: [...views, ...containers, ...components],
  imports: [
    SharedModule,
    // <==== a lot of material imports :D ====>
  ],
)
export class MainLayoutModule 

6 main-layout-view.component:

import  Component, OnInit  from "@angular/core";

import  Observable  from "rxjs";

import  SidenavService  from "@core/services";

@Component(
  selector: "rot-main-layout-view",
  template: `
    <rot-main-navbar></rot-main-navbar>
    <mat-drawer-container autosize hasBackdrop>
      <mat-drawer mode="over" [opened]="opened$ | async">
        <rot-main-sidenav></rot-main-sidenav>
      </mat-drawer>
      <div class="content-wrapper">
        <router-outlet></router-outlet>          <==== SUB ROUTER-OUTLET
      </div>
    </mat-drawer-container>
  `,
  styleUrls: ["./main-layout-view.component.scss"],
)
export class MainLayoutViewComponent implements OnInit 

  constructor(private _sidenavService: SidenavService) 

  ngOnInit(): void 

  get opened$(): Observable<boolean> 
    return this._sidenavService.opened$;
  


【讨论】:

@Nikita 我添加了一个真实的代码示例。如果有不清楚的地方,请告诉我; ) 谢谢你,顺便说一句,关于我的情况,我正在将 Angular 模块转换为延迟加载并忘记将其从 AppModule 导入中删除((我已使用 enableTracing: true 调试路由器模块,并且发现路由配置中有一些冗余路由,然后我知道应该在某处注册路由并检查我的延迟加载模块的引用,发现我忘记将其从 AppModule 导入中删除【参考方案2】:

在dashboard-routing.module中

而不是这个:

const routes: Routes = [
     path: '', component: DashboardComponent ,
     path: 'statistics', loadChildren: () => 
        import('./statistics/statistics.module').then(m => m.StatisticsModule)
    
];

这样做:

const routes: Routes = [
     path: '', component: DashboardComponent,
      children: [
           path: 'statistics', loadChildren: () => 
           import('./statistics/statistics.module').then(m => m.StatisticsModule)
          
      ]
    
];

【讨论】:

这似乎是错误的,你试过你的代码吗?为了使您的代码正常工作,作者必须将&lt;router-outlet&gt; 放在DashboardComponent 中,这是不需要的,因为他想通过延迟加载独立加载DashboardModuleStatisticsModule

以上是关于Angular 9 嵌套延迟加载模块,带有嵌套路由器出口的主要内容,如果未能解决你的问题,请参考以下文章

AngularJS“多重路由”嵌套模块——AngularJS“路由”嵌套学习资料教程

带有延迟加载路由的 Angular CLI HMR 热重载整个事情

Angular 4 嵌套路由器插座

延迟加载模块中的 Angular single-spa 延迟加载路由调用未定义的 webpack 错误

使用 Angular 1.5 组件的嵌套路由中的相对视图

懒加载Vue的父组件和所有嵌套路由