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

Angular 2:如何实现Material Table与Material Spinner的互斥显示?

Angular Material Table与Spinner互斥显示实现方案

嘿,这个需求其实很常见,核心就是通过一个状态变量来控制两者的显示/隐藏,我给你两种常用的实现方式,你可以根据自己的代码风格选:

方式一:手动管理加载状态变量

这是最直观的方式,适合大多数场景:

1. 在组件类中定义状态变量

首先在你的组件.ts文件里,声明一个布尔变量来标记加载状态,初始值设为true(因为页面加载时先显示Spinner):

import { Component, OnInit } from '@angular/core';
import { YourDataService } from './your-data.service';

@Component({
  selector: 'app-your-component',
  templateUrl: './your-component.component.html',
})
export class YourComponent implements OnInit {
  // 加载状态变量
  isLoading = true;
  // 表格数据
  tableData: any[] = [];
  // 表格列配置
  displayedColumns = ['name', 'age', 'email'];

  constructor(private dataService: YourDataService) {}

  ngOnInit(): void {
    this.loadTableData();
  }

  loadTableData(): void {
    // 开始加载时,设置为true
    this.isLoading = true;
    this.dataService.fetchYourData().subscribe({
      next: (data) => {
        this.tableData = data;
      },
      error: (err) => {
        console.error('数据加载失败:', err);
        // 即使出错,也要隐藏加载器
        this.isLoading = false;
      },
      complete: () => {
        // 加载完成(无论成功失败),隐藏加载器
        this.isLoading = false;
      },
    });
  }
}

2. 在模板中用*ngIf控制显示

然后在你的组件.html文件里,用*ngIf根据isLoading的值来切换表格和Spinner的显示:

<!-- 加载Spinner:只有当isLoading为true时显示 -->
<div *ngIf="isLoading" class="loading-container">
  <mat-spinner diameter="50"></mat-spinner>
</div>

<!-- Material表格:只有当isLoading为false时显示 -->
<mat-table *ngIf="!isLoading" [dataSource]="tableData">
  <!-- 示例列定义 -->
  <ng-container matColumnDef="name">
    <mat-header-cell *matHeaderCellDef> 姓名 </mat-header-cell>
    <mat-cell *matCellDef="let element"> {{element.name}} </mat-cell>
  </ng-container>

  <ng-container matColumnDef="age">
    <mat-header-cell *matHeaderCellDef> 年龄 </mat-header-cell>
    <mat-cell *matCellDef="let element"> {{element.age}} </mat-cell>
  </ng-container>

  <ng-container matColumnDef="email">
    <mat-header-cell *matHeaderCellDef> 邮箱 </mat-header-cell>
    <mat-cell *matCellDef="let element"> {{element.email}} </mat-cell>
  </ng-container>

  <mat-header-row *matHeaderRowDef="displayedColumns"></mat-header-row>
  <mat-row *matRowDef="let row; columns: displayedColumns;"></mat-row>
</mat-table>

3. 给Spinner加个居中样式

为了让Spinner在页面中间显示,你可以在组件的CSS里加个简单的样式:

.loading-container {
  display: flex;
  justify-content: center;
  align-items: center;
  height: 300px; /* 可以根据表格预期高度调整 */
}

方式二:使用Async Pipe(更简洁)

如果你的数据是通过Observable获取的,推荐用Angular的async pipe,它会自动帮你管理订阅和状态,不用手动设置isLoading:

1. 组件类中定义数据Observable

import { Component } from '@angular/core';
import { Observable } from 'rxjs';
import { YourDataService } from './your-data.service';

@Component({
  selector: 'app-your-component',
  templateUrl: './your-component.component.html',
})
export class YourComponent {
  // 直接用Observable存储数据
  tableData$: Observable<any[]>;
  displayedColumns = ['name', 'age', 'email'];

  constructor(private dataService: YourDataService) {
    this.tableData$ = this.dataService.fetchYourData();
  }
}

2. 模板中用*ngIf结合else块

<!-- 表格:当数据加载完成时显示 -->
<mat-table *ngIf="tableData$ | async as tableData; else loadingBlock" [dataSource]="tableData">
  <!-- 你的表格列定义(和方式一一致) -->
</mat-table>

<!-- 加载Spinner的else块 -->
<ng-template #loadingBlock>
  <div class="loading-container">
    <mat-spinner diameter="50"></mat-spinner>
  </div>
</ng-template>

这种方式更符合Angular的响应式编程理念,还能避免内存泄漏(因为async pipe会自动取消订阅)。

关键注意点

  • 无论数据加载成功还是失败,都要确保Spinner能隐藏,避免用户一直看到加载状态
  • 如果表格本身有数据为空的情况,可以在表格显示的条件里再加个tableData.length > 0,同时添加空状态提示(比如“暂无数据”的文字)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 04:50:44