Angular多特性模块复用同一父布局的路由配置问题
解决Angular特性模块复用布局与独立登录路由的问题
我来帮你搞定这个布局复用和路由配置的问题,你的思路方向是对的,只是在组件共享和路由结构上需要做些调整,避免重复渲染的问题。
核心问题分析
你之前遇到的布局重复渲染,是因为Angular不允许同一个组件在多个模块中被声明——每个组件只能属于一个模块,重复声明会导致Angular创建多个组件实例,自然就会重复渲染布局了。所以我们需要把布局组件抽成共享模块,让所有需要它的模块去导入使用。
步骤1:创建共享模块存放布局组件
首先新建一个SharedModule,把布局相关的组件(LayoutComponent、HeaderComponent、SideMenuComponent、FooterComponent)都放在这里,只声明一次,然后导出它们供其他模块使用:
// shared.module.ts import { NgModule } from '@angular/core'; import { CommonModule } from '@angular/common'; import { LayoutComponent } from './layout/layout.component'; import { HeaderComponent } from './header/header.component'; import { SideMenuComponent } from './side-menu/side-menu.component'; import { FooterComponent } from './footer/footer.component'; import { RouterModule } from '@angular/router'; // 布局里用到router-outlet,必须导入 @NgModule({ declarations: [ LayoutComponent, HeaderComponent, SideMenuComponent, FooterComponent ], imports: [ CommonModule, RouterModule ], exports: [ LayoutComponent // 导出布局组件,让其他模块能直接使用 ] }) export class SharedModule { }
步骤2:调整AppModule配置
把原来在AppModule里声明的布局组件移除,换成导入SharedModule,路由结构保持你的原有设计(登录路由直接挂载根路由,带布局的路由作为LayoutComponent的子路由):
// app.module.ts import { NgModule } from '@angular/core'; import { BrowserModule } from '@angular/platform-browser'; import { AppComponent } from './app.component'; import { DashboardOneComponent } from './dashboard-one/dashboard-one.component'; import { DashboardTwoComponent } from './dashboard-two/dashboard-two.component'; import { LoginComponent } from './login/login.component'; import { RouterModule, Routes } from '@angular/router'; import { AuthGuard } from './auth.guard'; import { SharedModule } from './shared/shared.module'; const appRoutes: Routes = [ { path: 'login', component: LoginComponent }, // 独立登录布局,直接用根router-outlet { path: '', component: LayoutComponent, children: [ { path: '', component: DashboardOneComponent}, { path: 'dashboardOne', component: DashboardOneComponent}, { path: 'dashboardTwo', component: DashboardTwoComponent} ], canActivate: [AuthGuard] } ]; @NgModule({ declarations: [ AppComponent, DashboardOneComponent, DashboardTwoComponent, LoginComponent // 移除布局组件声明,已经在SharedModule里处理了 ], imports: [ BrowserModule, RouterModule.forRoot( appRoutes, { enableTracing: true } // 调试用,上线记得去掉 ), SharedModule, // 导入共享模块 InventoryModule, WarehouseModule, UserModule, ], providers: [AuthGuard], bootstrap: [AppComponent] }) export class AppModule { }
步骤3:调整特性模块(以InventoryModule为例)
特性模块不需要再声明LayoutComponent,只需要导入SharedModule,并把自身路由配置为LayoutComponent的子路由(因为我们已经把特性模块导入到AppModule,它的路由会自动合并到根路由体系中,匹配LayoutComponent的子路由规则):
// inventory.module.ts import { NgModule } from '@angular/core'; import { CommonModule } from '@angular/common'; import { InventoryOneComponent } from './inventory-one/inventory-one.component'; import { InventoryTwoComponent } from './inventory-two/inventory-two.component'; import { RouterModule, Routes } from '@angular/router'; import { SharedModule } from '../shared/shared.module'; import { AuthGuard } from '../auth.guard'; const inventoryRoutes: Routes = [ { path: 'inventory', children: [ { path: '', component: InventoryOneComponent}, { path: 'inventoryOne', component: InventoryOneComponent}, { path: 'inventoryTwo', component: InventoryTwoComponent} ], canActivate: [AuthGuard] } ]; @NgModule({ declarations: [ InventoryOneComponent, InventoryTwoComponent // 绝对不要在这里声明LayoutComponent! ], imports: [ CommonModule, SharedModule, // 导入共享模块(确保能使用布局相关组件) RouterModule.forChild(inventoryRoutes) ], providers: [] }) export class InventoryModule { }
最终效果说明
- 访问
/login时,根router-outlet直接加载LoginComponent,没有头部、侧边栏和页脚,符合独立登录布局需求。 - 访问
/dashboardOne、/inventory等路由时,根router-outlet加载LayoutComponent,然后LayoutComponent内部的router-outlet会加载对应的仪表盘/库存组件,实现了布局的复用,且不会重复渲染。
内容的提问来源于stack exchange,提问作者Asad Shah
相关产品推荐
相关产品推荐

