我正在尝试在离子应用程序中加载大量元素(〜630个元素)。我对优化最初加载页面所需的时间特别感兴趣。
我尝试使用虚拟滚动来仅按需加载元素。这非常有用,因为我的页面可以快速加载,并且在呈现页面之前尝试加载所有630个元素没有延迟。取而代之的是,仅渲染视口中的项目,从而获得流畅的用户体验。
我的问题是这样
我正在使用搜索栏来过滤列表,而我的实现要求将所有项目加载到DOM中才能正确过滤。通过使用虚拟滚动,我的过滤器无法正常运行,因为除非它们在视口中,否则它们不会插入DOM。
我希望能够有一个页面可以快速加载但也可以被过滤。我可以使用虚拟滚动替代方法来更快地初始加载页面吗?还是应该更改过滤器实现?
这是我的代码:
home.html
<ion-searchbar (ionInput)="onSearch($event)" class="hymns-searchbar" placeholder="Search" [showCancelButton]="shouldShowCancel" (ionCancel)="onClear()"></ion-searchbar>
...
<ion-content padding>
<ion-list [virtualScroll]="hymns">
<div *virtualItem="let song; let i = index;"
id="songItems" approxItemHeight="62px" bufferRatio="10">
<button ion-item clear class="hymns-list-item"
[navPush]="songPage" [navParams]=song>
<h4 class="song-title">
<span class="song-number">{{i + 1}}</span>{{ song.title }}
</h4>
<small class="song-genre">{{song.category}}</small>
</button>
</div>
</ion-list>
</ion-content>
home.ts
public hymns: any;
private songItems:any;
ngOnInit() {
this.hymns = songs; // Array with 630 elements
}
onSearch(event) {
let val = event.target.value;
if (typeof val == 'undefined') {
// clear list
}
else {
val = val.toUpperCase();
this.songItems = document.querySelectorAll('#songItems');
for (let i = 0; i < this.hymns.length; i++) {
let title = this.hymns[i].title;
if (title.toUpperCase().indexOf(val) > -1) {
this.songItems[i].style.display = '';
}
else {
this.songItems[i].style.display = 'none';
}
}
}
答案 0 :(得分:1)
虚拟滚动是一种很好的优化机制。你应该离开它。
最好不要直接与DOM交互。 Angular为您提供了有关DOM的出色抽象。您可以尝试使用一个单独的数组来显示过滤后的值来优化搜索。
template
<ion-searchbar (ionInput)="onSearch($event)"></ion-searchbar>
<ion-list [virtualScroll]="displaySongs">
<ion-item *virtualItem="let item">
{{ item }}
</ion-item>
</ion-list>
ts
public displaySongs: [];
private allSongs: [];
ngOnInit() {
this.allSongs = songs; // Array with 630 elements
this.displaySongs = songs;
}
onSearch(event) {
const searchQuery = event.target.value.toUpperCase();
this.displaySongs = this.allSongs
.filter((song) => song.toUpperCase().includes(searchQuery));
}