动态加载的模块导致 Angular `<router-outlet>` 显示两次

Dynamically loaded module causes Angular `<router-outlet>` to display twice

此问题的解决方案在 中的某处,但我无法应用它,因为我的示例因动态加载的模块而不同。

我有一个嵌套的 <router-outlet> 设置;

应用结构:

app.component.ts       <router-outlet>
components/
    login/
        login-component.ts
    main/
        main-module.ts
        main-component.ts       <router-outlet>
        components/
            leaf-component.ts

以下内容摘自 app.module 并有效 iff​​ main-module 不是 动态加载。 IE。它仅在实例化 main-component 时有效。

const redirectUnauthorizedToLogin = () => redirectUnauthorizedTo(['/login']);
const redirectLoggedInToMain = () => redirectLoggedInTo(['/main']);

const appRoutes: Routes = [
  {
    path: 'login',
    pathMatch: 'full',
    component: LoginComponent,
    canActivate: [AngularFireAuthGuard],
    data: { authGuardPipe: redirectLoggedInToMain },
  },
  {
    path: '',
    component: MainComponent,
    canActivate: [AngularFireAuthGuard],
    data: { authGuardPipe: redirectUnauthorizedToLogin },
    children: [

      { path: '', redirectTo: '/main', pathMatch: 'full' },
      // ----> Render leaf-component in main-component <router-outlet>
      {
        path: 'main',
        pathMatch: 'full',
        component: LeafComponent,
      },

    ],
  },
  { path: '**', component: PageNotFoundComponent },
];

这行得通。但是当动态加载 LeafModule 时,MainComponent 被渲染了两次。 IE。当动态加载 main-module 并实例化 then main-component 时,它不起作用。

const appRoutes: Routes = [
  {
    path: 'login',
    pathMatch: 'full',
    component: LoginComponent,
    canActivate: [AngularFireAuthGuard],
    data: { authGuardPipe: redirectLoggedInToMain },
  },
  {
    path: '',
    component: MainComponent,
    canActivate: [AngularFireAuthGuard],
    data: { authGuardPipe: redirectUnauthorizedToLogin },
    children: [

      { path: '', redirectTo: '/main', pathMatch: 'full' },
      // ----> Dynamically load leaf-module
      // ----> Render leaf-component in main-component <router-outlet>
      {
        path: 'main',
        pathMatch: 'full',
        loadChildren: () => import('./components/main/components/leaf/leaf.module').then(m => m.LeafModule)
      },

    ],
  },
  { path: '**', component: PageNotFoundComponent },
];

解决方案详细信息

@inge-olaisen 的建议解决了我的问题,但为了完整起见,我想在这里添加一些细节。

我的错误是没有意识到动态加载的模块必须(?)有一个路由,即使该路由只加载默认模块:

import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { LeafComponent } from './leaf.component';

const routes: Routes = [
    {
        path: '',
        component: LeafComponent,
        pathMatch: 'full',
    },
];
@NgModule({
    imports: [
        RouterModule.forChild(routes),
    ],
    exports: [RouterModule]
})
export class LeafRoutingModule { }

这看起来还是有点多余,因为没有路由。但是因为我要懒加载组件,所以必须加上。

我还使用了单独的路由模块,这确实让事情变得更清楚了。

最后,Angular 8 | Nested Routing with Multiple RouterOutlet using loadChildren having own Router Modules Example Application, is probably the simplest and most complete example of nested routing with lazy-loaded modules out there (IMO). It also uses a recent version of Angular and thus the new load loadChildren: () => import('./foo.module').then(m => m.FooModule) syntax. It also has a StackBlitz demo

我们缺少一些关键信息。 leaf.module 有自己的路由器模块吗?例如一片叶子-routing.module.ts。该路由模块反过来应该具有加载 LeafComponent 的 '' 的路径匹配。

如果您没有该路由模块,该模块将不知道要查找哪条路由,我假设问题与您链接到的人所遇到的问题相同,但您却不见了LeafRoutingModule 的 '' 路径。