實作虛擬捲動功能,讓大型清單的回應速度更快。
捲動清單是目前最常見的 UI 模式之一,無論是在喜愛的社群媒體網站上瀏覽無限捲動的動態消息,或是在企業資訊主頁中瀏覽,都可看到這種模式。當捲動清單變得非常長 (數百、數千或數十萬個項目) 時,應用程式效能可能會受到影響。
大型清單的載入速度可能較慢,因為應用程式必須預先載入及轉譯所有資料。此外,由於清單中的每個項目都可能包含多媒體資料、媒體和功能,因此轉譯和瀏覽速度也可能較慢。
使用者在載入或捲動網頁時可能會遇到問題,導致他們感到挫折並放棄網頁。
在 Angular 中使用 Component Dev Kit 進行虛擬捲動
虛擬捲動是解決這些規模問題的主要技術。虛擬捲動功能會提供大小適中的捲軸,並可瀏覽清單,而不需要應用程式將整個清單保留在記憶體中,或在頁面上算繪,因此會給人一種清單非常大的印象。
在 Angular 中,虛擬捲動功能是由元件開發套件 (CDK) 提供。只要修改疊代清單的方式,並提供幾個額外的設定參數,CDK 的虛擬捲動功能就會自動管理清單的虛擬轉譯,進而提升網頁效能和回應速度。
系統不會一次轉譯整個清單,而是只轉譯螢幕上顯示的部分項目 (加上一小段緩衝區)。當使用者瀏覽時,系統會計算並算繪新的項目子集,並視需要重複使用現有的 DOM。
本文其餘部分將逐步說明如何設定基本虛擬捲動。如需完整的工作範例,請參閱這個範例應用程式:
設定虛擬捲動
首先,請確認您已使用偏好的套件管理工具安裝 @angular/cdk。如要使用 npm 安裝,請在終端機中執行下列指令:
npm install --save @angular/cdk
在應用程式中新增 ScrollingModule
安裝 CDK 後,請從 @angular/cdk/scrolling 套件匯入 ScrollingModule,用於處理虛擬捲動。然後將其新增至模組的匯入陣列:
import {ScrollingModule} from '@angular/cdk/scrolling';
...
imports: [
ScrollingModule
...
]
...
建立可視區域
如要瞭解套件的運作方式,請嘗試建立一個元件,其中包含 0 到 99,999 的數字清單:
@Component({
template: `<div *ngFor="let item of list">{{item}}</div>`
})
export class ScrollComponent {
list = Array.from({length: 100000}).map((_, i) => i);
}
瀏覽器算繪應用程式時,必須算繪 100,000 個獨立的 <div> 元素。這對基本文字節點來說可能沒問題,但重複範本中的任何複雜度都無法妥善擴充,且任何事件監聽器都會大幅增加。
如要新增虛擬捲動功能並避免這些問題,您必須將清單包裝在 <cdk-virtual-scroll-viewport> 元素中,建立可視區域:
@Component({
template: `<cdk-virtual-scroll-viewport>
<div *ngFor="let item of list">{{item}}</div>
</cdk-virtual-scroll-viewport>`
})
export class ScrollComponent {
list = Array.from({length: 100000}).map((_, i) => i);
}
由於 ScrollingModule 會動態轉譯清單的子集,因此您必須使用標準 CSS 指定可視區域的高度。您也需要指定 itemSize,向可視區域提供內容提示。模組會使用這項資訊,判斷在特定時間點要在 DOM 中保留多少項目,以及如何算繪適當大小的捲軸。
@Component({
template: `<cdk-virtual-scroll-viewport itemSize="18" style="height:80vh">
<div *ngFor="let item of list">{{item}}</div>
</cdk-virtual-scroll-viewport>`
})
export class ScrollComponent {
list = Array.from({length: 100000}).map((_, i) => i);
}
最後,將 *ngFor 轉換為 *cdkVirtualFor:
@Component({
template: `<cdk-virtual-scroll-viewport itemSize="18" style="height:80vh">
<div *cdkVirtualFor="let item of list">{{item}}</div>
</cdk-virtual-scroll-viewport>`
})
export class ScrollComponent {
list = Array.from({length: 100000}).map((_, i) => i);
}
可視區域不會疊代整個清單,而是動態識別並疊代清單中正確的子集,供使用者查看。現在,當使用者載入頁面時,CDK 應會轉譯適合螢幕大小的清單子集 (加上一些緩衝區),而可視區域中的任何捲動事件都會載入並轉譯適當的清單子集:
進一步
CDK 的虛擬捲動功能遠比這個基本範例更強大。在範例應用程式中,整個清單都在記憶體中,但可以視需要擷取清單,以用於更複雜的應用程式。如要進一步瞭解 ScrollingModule 的其他功能和 cdkVirtualOf 指令,請參閱 CDK 說明文件中的 Scrolling 相關資訊。