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

Angular项目中如何将路由加载组件的数据传递给sidebar组件

Angular子路由组件向Sidebar传递请求耗时数据的可行方案

方案1:共享状态服务(优先推荐,适配绝大多数场景)

适合任意组件间通信,不受组件层级关系限制,实现简单易维护。
实现步骤:

  • 第一步:创建全局单例的状态管理服务
// request-stats.service.ts
import { Injectable } from '@angular/core';
import { BehaviorSubject } from 'rxjs';

// 定义请求耗时数据结构
export interface RequestStat {
  url: string;
  duration: number;
  timestamp: number;
  isError?: boolean;
}

@Injectable({ providedIn: 'root' })
export class RequestStatsService {
  // 用BehaviorSubject存储历史数据,新订阅者也能拿到之前的统计结果
  private readonly statsSubject = new BehaviorSubject<RequestStat[]>([]);
  public readonly stats$ = this.statsSubject.asObservable();

  // 新增耗时统计
  addStat(stat: RequestStat) {
    const currentStats = this.statsSubject.value;
    this.statsSubject.next([...currentStats, stat]);
  }

  // 可选:清空统计数据,比如切换路由时重置
  clearStats() {
    this.statsSubject.next([]);
  }
}
  • 第二步:在路由子组件中注入服务,请求完成后提交耗时数据
// models-table.component.ts 等业务组件
import { RequestStatsService } from './request-stats.service';

constructor(private statsService: RequestStatsService) {}

fetchModelData() {
  const requestStartTime = Date.now();
  this.http.get('/api/models').subscribe({
    next: (res) => {
      // 计算请求耗时,提交到服务
      const duration = Date.now() - requestStartTime;
      this.statsService.addStat({
        url: '/api/models',
        duration: duration,
        timestamp: Date.now()
      });
      // 原有业务逻辑
    },
    error: (err) => {
      // 错误请求也可以按需统计
      const duration = Date.now() - requestStartTime;
      this.statsService.addStat({
        url: '/api/models',
        duration: duration,
        timestamp: Date.now(),
        isError: true
      });
    }
  })
}
  • 第三步:在Sidebar组件中订阅数据渲染
// sidebar.component.ts
import { RequestStatsService } from './request-stats.service';

requestStats: RequestStat[] = [];

constructor(private statsService: RequestStatsService) {}

ngOnInit() {
  this.statsService.stats$.subscribe(stats => {
    this.requestStats = stats;
  });
}

// 推荐直接在模板中使用async管道,无需手动管理订阅生命周期:
// <div *ngFor="let stat of statsService.stats$ | async">
//   {{stat.url}} 耗时:{{stat.duration}}ms
// </div>

方案2:父组件中转(适合仅少量子组件需要传数据的场景)

利用LayoutComponent作为子路由组件和Sidebar的公共父组件,作为中间层传递数据,无需额外创建服务。
实现步骤:

  • 第一步:在路由子组件中定义Output事件,请求完成后抛出数据
// models-table.component.ts
import { Output, EventEmitter } from '@angular/core';
import { RequestStat } from './request-stats.service';

@Output() statGenerated = new EventEmitter<RequestStat>();

fetchModelData() {
  const requestStartTime = Date.now();
  this.http.get('/api/models').subscribe(res => {
    const duration = Date.now() - requestStartTime;
    this.statGenerated.emit({
      url: '/api/models',
      duration: duration,
      timestamp: Date.now()
    });
  });
}
  • 第二步:LayoutComponent监听router-outlet的激活事件,绑定子组件的Output
    修改default-layout.component.ts模板:
<div class="app-container">
  <router-outlet (activate)="onChildActivate($event)"></router-outlet>
</div>

添加组件逻辑:

// default-layout.component.ts
import { Subscription } from 'rxjs';

private childSub?: Subscription;
sidebarStats: RequestStat[] = [];

onChildActivate(component: any) {
  // 销毁之前的订阅,避免内存泄漏
  this.childSub?.unsubscribe();
  // 判断当前子组件是否有statGenerated事件
  if (component.statGenerated) {
    this.childSub = component.statGenerated.subscribe(stat => {
      this.sidebarStats = [...this.sidebarStats, stat];
    });
  }
}

ngOnDestroy() {
  this.childSub?.unsubscribe();
}
  • 第三步:给Sidebar添加Input属性,绑定数据
    修改default-layout.component.ts模板:
<fbo-sidebar 
  (changeSidebarPosition)="onChangeSidebarPosition($event)"
  [requestStats]="sidebarStats"
></fbo-sidebar>
// sidebar.component.ts
@Input() requestStats: RequestStat[] = [];

方案3:HTTP拦截器全局采集(适合需要统计所有请求耗时的场景)

如果需要统计应用内所有HTTP请求的耗时,无需在每个业务组件单独计算,直接通过拦截器全局采集,自动推送到共享服务。
实现步骤:

  • 第一步:创建HTTP拦截器
// request-duration.interceptor.ts
import { Injectable } from '@angular/core';
import { HttpRequest, HttpHandler, HttpEvent, HttpInterceptor } from '@angular/common/http';
import { Observable } from 'rxjs';
import { tap } from 'rxjs/operators';
import { RequestStatsService } from './request-stats.service';

@Injectable()
export class RequestDurationInterceptor implements HttpInterceptor {
  constructor(private statsService: RequestStatsService) {}

  intercept(request: HttpRequest<unknown>, next: HttpHandler): Observable<HttpEvent<unknown>> {
    const startTime = Date.now();
    return next.handle(request).pipe(
      tap({
        next: () => {
          const duration = Date.now() - startTime;
          this.statsService.addStat({
            url: request.url,
            duration: duration,
            timestamp: Date.now()
          });
        },
        error: () => {
          const duration = Date.now() - startTime;
          this.statsService.addStat({
            url: request.url,
            duration: duration,
            timestamp: Date.now(),
            isError: true
          });
        }
      })
    );
  }
}
  • 第二步:在AppModule的providers中注册拦截器
// app.module.ts
import { HTTP_INTERCEPTORS } from '@angular/common/http';
import { RequestDurationInterceptor } from './request-duration.interceptor';

@NgModule({
  providers: [
    {
      provide: HTTP_INTERCEPTORS,
      useClass: RequestDurationInterceptor,
      multi: true
    }
  ]
})
export class AppModule {}

后续Sidebar直接订阅RequestStatsService的stats$即可拿到所有请求的耗时数据。


内容的提问来源于stack exchange,提问作者Hadock

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.26 12:54:03