You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.19 22:30:55