Angular嵌套路由问题:需隐藏父组件仅展示子组件视图
解决方案:访问子组件时隐藏父组件视图
要实现访问historial.component时隐藏casilleros.component的原有视图,仅显示子组件内容,可通过以下两种方式实现,推荐第一种更清晰的组件拆分方案:
方案一:拆分组件+调整路由结构
这种方式将父组件的列表内容拆分到独立组件,让CasillerosComponent仅作为路由容器,彻底避免父内容与子内容同时显示的问题。
1. 创建CasillerosListComponent
将原casilleros.component.html中的搜索框、表格内容迁移到新组件CasillerosListComponent中:
<!-- casilleros-list.component.html --> <div class="container mt-4"> <div class="d-flex justify-content-between mb-3"> <input type="text" class="form-control w-50" placeholder="Buscar"> </div> <table class="table table-striped"> <thead> <tr> <th></th> <th>Referencia</th> <th>Ubicación</th> <th>Activo</th> <th>Ocupado</th> <th>Acción</th> </tr> </thead> <tbody> <tr *ngFor="let item of items; let i = index;"> <td>{{i}}</td> <td>{{ item.referencia }}</td> <td>{{ item.ubicacion }}</td> <td> <div class="form-check form-switch"> <input class="form-check-input" type="checkbox" id="activo{{ item.referencia }}" checked> </div> </td> <td> <div class="form-check form-switch"> <input class="form-check-input" type="checkbox" id="ocupado{{ item.referencia }}" checked> </div> </td> <td> <button (click)="goToHistorial(item)" class="btn btn-sm"><i class="bi bi-search"></i></button> <button class="btn btn-sm"><i class="bi bi-pencil"></i></button> <button class="btn btn-sm"><i class="bi bi-trash"></i></button> </td> </tr> </tbody> </table> </div>
对应的组件类也迁移过去:
// casilleros-list.component.ts import { Component } from '@angular/core'; import { Router, ActivatedRoute } from '@angular/router'; @Component({ selector: 'app-casilleros-list', templateUrl: './casilleros-list.component.html', styleUrls: ['./casilleros-list.component.css'] }) export class CasillerosListComponent { constructor(private router: Router, private route: ActivatedRoute) {} items = [ { referencia: 101, ubicacion: 'Vinilo' }, { referencia: 102, ubicacion: 'Vinilo' }, { referencia: 103, ubicacion: 'Vinilo' }, { referencia: 104, ubicacion: 'Vinilo' }, { referencia: 105, ubicacion: 'Vinilo' }, { referencia: 106, ubicacion: 'Vinilo' }, { referencia: 107, ubicacion: 'Vinilo' }, { referencia: 108, ubicacion: 'Vinilo' }, { referencia: 109, ubicacion: 'Vinilo' }, { referencia: 110, ubicacion: 'Vinilo' } ]; goToHistorial(item: any) { this.router.navigate(['../historial'], { relativeTo: this.route }); } }
2. 修改路由配置
更新app-routing.module.ts,将casilleros的子路由设置为默认显示列表组件,historial作为同级子路由:
// app-routing.module.ts const routes: Routes = [ { path: '', redirectTo: 'login', pathMatch: 'full' }, { path: 'login', component: LoginComponent }, { path: 'navbar', component: NavbarComponent }, { path: 'dashboard', component: DashboardComponent, data: { breadcrumb: 'Dashboard' }, children: [ { path: 'permisos', component: PermisosComponent, data: { breadcrumb: 'Permisos' }}, { path: 'operarios', component: OperariosComponent, data: { breadcrumb: 'Operarios' }}, { path: 'maquinas', component: MaquinasComponent, data: { breadcrumb: 'Máquinas' }}, { path: 'materiales', component: MaterialesComponent, data: { breadcrumb: 'Materiales' }}, { path: 'casilleros', component: CasillerosComponent, data: { breadcrumb: 'Casilleros' }, children: [ { path: '', component: CasillerosListComponent }, // 默认显示列表 { path: 'historial', component: HistorialComponent, data: { breadcrumb: 'Historial' }} ] }, ] }, ];
3. 简化CasillerosComponent
将casilleros.component.html简化为仅包含路由出口:
<!-- casilleros.component.html --> <router-outlet></router-outlet>
组件类也简化为基础结构:
// casilleros.component.ts import { Component } from '@angular/core'; @Component({ selector: 'app-casilleros', templateUrl: './casilleros.component.html', styleUrls: ['./casilleros.component.css'] }) export class CasillerosComponent {}
方案二:在父组件中通过路由状态控制显示
如果不想拆分组件,可通过监听路由状态,动态控制父组件内容的显示:
1. 修改CasillerosComponent类
添加路由监听,判断是否有激活的子路由:
// casilleros.component.ts import { Component, OnInit } from '@angular/core'; import { Router, ActivatedRoute } from '@angular/router'; @Component({ selector: 'app-casilleros', templateUrl: './casilleros.component.html', styleUrls: ['./casilleros.component.css'] }) export class CasillerosComponent implements OnInit { hasActiveChildRoute = false; constructor(private router: Router, private route: ActivatedRoute) {} ngOnInit(): void { this.router.events.subscribe(() => { this.hasActiveChildRoute = this.route.firstChild !== null; }); } items = [ { referencia: 101, ubicacion: 'Vinilo' }, { referencia: 102, ubicacion: 'Vinilo' }, { referencia: 103, ubicacion: 'Vinilo' }, { referencia: 104, ubicacion: 'Vinilo' }, { referencia: 105, ubicacion: 'Vinilo' }, { referencia: 106, ubicacion: 'Vinilo' }, { referencia: 107, ubicacion: 'Vinilo' }, { referencia: 108, ubicacion: 'Vinilo' }, { referencia: 109, ubicacion: 'Vinilo' }, { referencia: 110, ubicacion: 'Vinilo' } ]; goToHistorial(item: any) { this.router.navigate(['historial'], { relativeTo: this.route }); } }
2. 修改父组件模板
用*ngIf控制父内容的显示,仅当无激活子路由时展示:
<!-- casilleros.component.html --> <div class="container mt-4" *ngIf="!hasActiveChildRoute"> <div class="d-flex justify-content-between mb-3"> <input type="text" class="form-control w-50" placeholder="Buscar"> </div> <table class="table table-striped"> <!-- 原表格内容保持不变 --> </table> </div> <router-outlet></router-outlet>
3. 更新路由配置
去掉命名出口,改为普通嵌套路由:
// app-routing.module.ts const routes: Routes = [ { path: '', redirectTo: 'login', pathMatch: 'full' }, { path: 'login', component: LoginComponent }, { path: 'navbar', component: NavbarComponent }, { path: 'dashboard', component: DashboardComponent, data: { breadcrumb: 'Dashboard' }, children: [ { path: 'permisos', component: PermisosComponent, data: { breadcrumb: 'Permisos' }}, { path: 'operarios', component: OperariosComponent, data: { breadcrumb: 'Operarios' }}, { path: 'maquinas', component: MaquinasComponent, data: { breadcrumb: 'Máquinas' }}, { path: 'materiales', component: MaterialesComponent, data: { breadcrumb: 'Materiales' }}, { path: 'casilleros', component: CasillerosComponent, data: { breadcrumb: 'Casilleros' }, children: [ { path: 'historial', component: HistorialComponent, data: { breadcrumb: 'Historial' }} ] }, ] }, ];
两种方案都能实现需求,方案一的组件拆分更符合Angular的组件化设计原则,便于后续维护和扩展。
内容的提问来源于stack exchange,提问作者Pedro Madrigal
相关产品推荐
相关产品推荐

