PrimeNg下拉框虚拟滚动懒加载问题求助(v14.2.3)
PrimeNg v14.2.3 下拉框虚拟滚动+懒加载+搜索修复方案
问题核心分析
你的代码存在以下几个关键问题导致懒加载失效:
- 重复请求全量数据:每次触发懒加载都重新调用
getCity()拉取全部1000条数据,既浪费性能,也导致切片逻辑无法正确累积加载 - 无效的
first变量修改:手动修改局部变量first += 100没有意义,LazyLoadEvent的first参数会由PrimeNG根据滚动位置自动传递 - 未初始化首次加载:组件初始化时仅设置
loading=true,没有触发首次数据加载 - 搜索与懒加载未联动:开启了过滤功能,但未处理搜索时的懒加载逻辑
修复后的完整代码
组件代码(city.component.ts)
import { Component, OnInit } from '@angular/core'; import {CityService} from "../../services/city.service"; import {City} from "../../common/City"; import {ConfirmationService, LazyLoadEvent, MessageService} from "primeng/api"; @Component({ selector: 'app-city', templateUrl: './city.component.html', styleUrls: ['./city.component.scss'] }) export class CityComponent implements OnInit { city: City = new City; cities: City[] = []; dropdownCities: City[] = []; allCities: City[] = []; // 缓存全量城市数据 totalRecords: number = 0; loading: boolean = false; cityDialog: boolean = false; submitted: boolean = false; filterText: string = ''; // 绑定搜索过滤文本 constructor( private cityService: CityService, private messageService: MessageService, private confirmationService: ConfirmationService ) { } ngOnInit(): void { this.loading = true; // 初始化加载全量数据并缓存,避免重复请求 this.cityService.getCity().then(res => { this.allCities = res; this.totalRecords = res.length; // 触发首次懒加载,加载前100条 this.loadDropdownCities({first: 0, rows: 100}); this.loading = false; }); } loadDropdownCities(event: LazyLoadEvent) { this.loading = true; const first = event.first ?? 0; const rows = event.rows ?? 100; // 先处理搜索过滤逻辑 let filteredData = this.allCities; if (this.filterText.trim()) { filteredData = this.allCities.filter(city => city.name.toLowerCase().includes(this.filterText.toLowerCase()) ); } // 更新总记录数,让PrimeNG正确计算滚动范围 this.totalRecords = filteredData.length; // 切片获取当前需要加载的数据段 this.dropdownCities = filteredData.slice(first, first + rows); this.loading = false; } // 监听搜索框的过滤事件,重新加载第一页数据 onFilterChange(event: any) { this.filterText = event.filter; this.loadDropdownCities({first: 0, rows: 100}); } }
模板代码(city.component.html)
<p-dropdown [options]="dropdownCities" optionLabel="name" [filter]="true" filterBy="name" (onFilterChange)="onFilterChange($event)" [showClear]="true" placeholder="Select a City" [virtualScroll]="true" [itemSize]="31" [lazy]="true" [totalRecords]="totalRecords" (onLazyLoad)="loadDropdownCities($event)" > <ng-template pTemplate="loader"> <div class="text-center p-3">加载中...</div> </ng-template> </p-dropdown>
关键修改说明
- 缓存全量数据:新增
allCities变量存储所有城市数据,仅在组件初始化时请求一次,后续懒加载直接从缓存切片 - 初始化首次加载:在
ngOnInit中加载完全量数据后,主动触发一次懒加载请求前100条数据 - 联动搜索与懒加载:通过
onFilterChange事件监听搜索输入,每次搜索时重新加载过滤后的第一页数据 - 绑定
totalRecords:模板中添加[totalRecords]="totalRecords",让PrimeNG知道总数据量,从而正确计算滚动触发懒加载的时机 - 简化loader模板:加载状态模板不需要接收
city参数,改为通用的加载提示
内容的提问来源于stack exchange,提问作者StilyNeedsHelp
相关产品推荐
相关产品推荐

