angular+rxjs無限滾動加載組件輪子

前言

昨天將以前收藏的一篇 Angular 和 RxJS 實現的無限滾動加載文章仔細看完,並動手實現了一遍代碼。項目中也用到過相似的滾動加載功能,就當是給本身造個輪子用了。html

由於原文章主要側重於知識點的講解和代碼邏輯實現,造出來的組件並不具有通用性,因此本身在源碼的基礎上抽取出了一個通用性的infinite-scroll的抽象組件類,使其能適用於任何滾動加載型的應用場景。git

代碼

先看抽象組件類:InfiniteScrollComponentgithub

export abstract class InfiniteScrollComponent<T> {
    private cache = [];
    protected itemHeight: number;
    protected numberOfItems: number;
    protected isLoading = false;
    protected isEnding = false;

    get itemResults(): Observable<T> {
        return this.itemResults$;
    }

    /** core */
    // 手動決定加載第幾頁數據的流
    private pageByManual$ = ...
    // scroll 事件的流
    private pageByScroll$ = ...
    // resize 事件的流
    private pageByResize$ = ...
    // 合併上述三個頁碼流
    private pageToLoad$ = ...
    // 基於pageToLoad$流來建立一個新的流,它將包含無限滾動加載列表中的數據
    private itemResults$ = ...
    /** end core */    

    abstract appendData(page: number): Observable<T>;
}

核心代碼部分基本照抄,只是將itemResults$中的http服務請求修改爲調用一個抽象的appendData()函數。另外,爲了屏蔽外界組件對rxjs流的困惑,增長了一個get itemResults()屬性。最後增長了兩個狀態字段isLoading和isEnding,分別表示加載中和無更多數據,提升界面的友好性。angular2

爲了可以支持自定義的model,這裏用了<T>泛型。
因爲該類是一個抽象類,因此須要外部組件來繼承並實現抽象方法:app

export class InfiniteScrollListComponent extends InfiniteScrollComponent<string>
  implements OnInit {
  constructor(private infiniteScrollService: InfiniteScrollService) {
    super();
  }

  ngOnInit() {
    this.itemHeight = 40;
    this.numberOfItems = 10;
  }

  appendData(page: number): Observable<string> {
    return this.infiniteScrollService.loadByPage(page);
  }
}

在該類的ngOnInit()函數中,設置了每一個item的高度(即每行的高度)和每頁加載的條目數。而後實現了appendData()方法,在這個方法裏就能夠根據業務邏輯去獲取到不一樣的數據了。async

值得注意的是,appendData()方法的page參數是存儲抽象類中的,其實這個page參數也是整個數據流的核心,不管是哪一種事件流,最終都轉化爲了計算出當前page值。函數

至此,基本就完工了,視圖頁能夠自由發揮了。好比:flex

<table>
  <tbody>
    <tr *ngFor="let item of itemResults|async" [style.height]="itemHeight + 'px'">
      <td>{{item.name}}</td>
    </tr>
  </tbody>
</table>
<div style="display: flex; justify-content: space-around;">
  <nz-spin *ngIf="!isEnding" [nzSize]="'small'" [nzSpinning]="isLoading" [nzTip]="'正在讀取數據...'"></nz-spin>
  <span *ngIf="isEnding">沒有更多數據了...</span>
</div>

項目源碼已開源在github上,歡迎issue和star。this

參考

Infinite scroll in Angular an RxJS
譯. 使用 Angular 和 RxJS 實現的無限滾動加載
視口的寬高與滾動高度spa

相關文章
相關標籤/搜索