如何有效地加载离子中的大列表?

时间:2018-11-16 23:57:07

标签: angular typescript ionic-framework

我正在尝试在离子应用程序中加载大量元素(〜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';
        }
      }
    }

1 个答案:

答案 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));
}