昨天將以前收藏的一篇 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