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

如何优化mat-select组件加载200+数据时的性能?

嘿,我之前也碰到过mat-select加载大量数据卡顿的问题,这几个方案亲测有效,你可以根据自己的场景选择:

1. 虚拟滚动(最推荐)

这是解决大量DOM元素渲染卡顿的核心方案——Angular CDK的虚拟滚动只会渲染当前可见区域的选项,不管你有多少条数据,DOM里始终只有少量元素。

首先要导入滚动模块:

import { ScrollingModule } from '@angular/cdk/scrolling';

然后修改你的模板:

<mat-form-field class="example-full-width">
  <mat-label>Work</mat-label>
  <mat-select formControlName="works_id">
    <!-- 设置虚拟滚动视口,itemSize是每个选项的高度(单位px) -->
    <cdk-virtual-scroll-viewport itemSize="48" class="virtual-scroll-container">
      <!-- 把*ngFor换成*cdkVirtualFor -->
      <mat-option *cdkVirtualFor="let work of works" [value]="work.work_id">
        {{work.work_name}}
      </mat-option>
    </cdk-virtual-scroll-viewport>
  </mat-select>
</mat-form-field>

给视口加个固定高度的样式:

.virtual-scroll-container {
  height: 300px; /* 根据需求调整高度 */
}
2. 实时搜索过滤

给mat-select加个搜索框,用户输入时实时过滤选项,减少需要渲染的条目数量。

组件里添加过滤逻辑:

import { FormBuilder, FormGroup } from '@angular/forms';

export class YourComponent {
  form: FormGroup;
  works: any[]; // 原始全量数据
  filteredWorks: any[]; // 过滤后的数据

  constructor(private fb: FormBuilder) {
    this.form = this.fb.group({
      works_id: [''],
      workSearch: ['']
    });

    // 监听搜索输入,实时过滤
    this.form.get('workSearch')?.valueChanges.subscribe(searchTerm => {
      this.filteredWorks = this.works.filter(work => 
        work.work_name.toLowerCase().includes(searchTerm?.toLowerCase() || '')
      );
    });
  }
}

模板修改为带搜索的结构:

<mat-form-field class="example-full-width">
  <mat-label>Work</mat-label>
  <!-- 搜索输入框 -->
  <input matInput placeholder="搜索工作项" formControlName="workSearch">
  <mat-select formControlName="works_id">
    <mat-option *ngFor="let work of filteredWorks" [value]="work.work_id">
      {{work.work_name}}
    </mat-option>
  </mat-select>
</mat-form-field>
3. 分页懒加载

如果数据是从后端获取的,可以做分页加载——只先渲染第一页(比如50条),当用户滚动到列表底部时,再加载下一页数据。

模板里添加加载更多选项:

<mat-form-field class="example-full-width">
  <mat-label>Work</mat-label>
  <mat-select formControlName="works_id">
    <mat-option *ngFor="let work of displayedWorks" [value]="work.work_id">
      {{work.work_name}}
    </mat-option>
    <!-- 加载更多选项 -->
    <mat-option *ngIf="hasMoreData" (click)="loadNextPage()">
      加载更多...
    </mat-option>
  </mat-select>
</mat-form-field>

组件里实现分页逻辑:

export class YourComponent {
  displayedWorks: any[] = [];
  currentPage = 1;
  pageSize = 50;
  hasMoreData = true;

  ngOnInit() {
    // 初始化加载第一页
    this.loadPage(this.currentPage);
  }

  loadPage(page: number) {
    // 调用后端接口获取分页数据,这里是示例逻辑
    this.yourApiService.getWorks(page, this.pageSize).subscribe(data => {
      // 如果返回的数据少于每页数量,说明没有更多数据了
      if (data.length < this.pageSize) {
        this.hasMoreData = false;
      }
      // 合并新数据(用immutable方式避免变更检测问题)
      this.displayedWorks = [...this.displayedWorks, ...data];
      this.currentPage++;
    });
  }

  loadNextPage() {
    this.loadPage(this.currentPage);
  }
}
4. 优化变更检测

把组件设置为OnPush变更检测策略,减少不必要的视图更新,尤其是数据量大的时候能明显提升性能。

import { ChangeDetectionStrategy, Component } from '@angular/core';

@Component({
  selector: 'your-component',
  templateUrl: './your-component.html',
  changeDetection: ChangeDetectionStrategy.OnPush // 开启OnPush
})
export class YourComponent {
  // 注意:更新数据时要用immutable方式(比如扩展运算符),不要直接修改原数组
  updateWorks(newWorks: any[]) {
    this.works = [...newWorks];
  }
}
5. 简化选项模板

如果你的mat-option里有复杂的DOM结构(比如图片、嵌套组件),尽量简化——越简单的模板渲染速度越快,必要时可以用ng-template延迟加载复杂内容。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.12 05:05:42