如何优化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
相关产品推荐
相关产品推荐

