动态加载的模块导致 Angular `<router-outlet>` 显示两次
Dynamically loaded module causes Angular `<router-outlet>` to display twice
此问题的解决方案在 中的某处,但我无法应用它,因为我的示例因动态加载的模块而不同。
我有一个嵌套的 <router-outlet>
设置;
localhost:4200/login
在顶级组件中呈现 LoginComponent
,AppComponent
localhost:4200/main
在顶级组件中呈现 MainComponent
,AppComponent
MainComponent
包含 <router-outlet>
,其中呈现 LeafComponent
。
应用结构:
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 的 '' 路径。
此问题的解决方案在
我有一个嵌套的 <router-outlet>
设置;
localhost:4200/login
在顶级组件中呈现LoginComponent
,AppComponent
localhost:4200/main
在顶级组件中呈现MainComponent
,AppComponent
MainComponent
包含<router-outlet>
,其中呈现LeafComponent
。
应用结构:
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 的 '' 路径。