無限滾動已經存在了一段時間了。 基本想法:當您滾動時,新內容會在底部加載,從而創建看似無窮無盡的滾動。 實作起來很簡單,但如果沒有仔細規劃,效能就會受到影響。 經過幾次內容重新獲取後,您可能會擁有數百個 DOM 元素,其中許多元素是看不見的。 幸運的是,存在一些模式可以緩解這種情況,我們將使用 Angular 來探索一種模式。
這是我們想要避免的。
虛擬滾動在任何時候僅渲染大列表的子集——與無限滾動不同。 它非常適合一次渲染所有內容效率低下的大型資料集。 僅渲染可見(和近乎可見)的項目;當使用者捲動時,項目會動態交換。 這顯著減少了 DOM 元素,從而提高了效能。
虛擬滾動透過建立與視窗高度匹配的容器來運作。 只有可見項目(加上緩衝區)才會在此容器中以特定的滾動深度呈現,並透過 CSS 進行管理。 捲動更新容器,顯示新項目並刪除視圖以外的項目,調整滾動深度。 將此與無限滾動相結合,創建一個幾乎無限的列表,而不會造成效能損失。
下面的範例顯示了包含數千個項目的列表,但一次最多渲染 8 個。 滾動會調整 CSS 滾動高度,產生列表更長的錯覺。
讓我們建立一個 Angular 應用程序,從 Reddit 的分頁 API 獲取媒體並將其顯示在虛擬滾動列表中。 它將包括一個用於子 Reddit 選擇的搜尋欄和一個過濾器。 向下捲動可載入更多內容。 我們的關鍵要求:
我們將使用 @angular/cdk
套件(包含 Virtual Scroller 元件)。使用npm i @angular/cdk
安裝它。
雖然此範例使用 Angular,但類似的模式也適用於 React、Vue 或 vanilla JavaScript。 此處提供了說明基本原理的基本示範。
首先,我們建立一個服務,使用 Angular 的 HttpClient
和 RxJS Observables 從 Reddit API 取得內容來管理 subreddit 名稱和過濾器。 (為簡潔起見,省略了一些程式碼;完整的實作在這裡)。
<code class="language-typescript">// ... (Omitted for brevity) ...</code>
內容取得方法在資料請求期間追蹤特定屬性。 page
屬性被加入到查詢字串中,以確保在最後一項之後取得新內容。 我們也過濾掉 NSFW 內容和缺少貼文提示的項目。這可確保僅顯示預期的內容。
<code class="language-typescript">// ... (Omitted for brevity) ...</code>
query$
observable(之前被省略)在取得內容之前合併不同的 observable 流。 scan
運算子結合了先前和目前的串流結果,建立跨多個頁面的大型資料數組。
這允許廣泛滾動;只有 subreddit 名稱或過濾器更改才會觸發完整的重新獲取。 nextPage
是 query$
的屬性,儲存目前集合中的最後一個項目 ID,用於確定在接近虛擬捲軸底部時要取得的下一頁。
<code class="language-typescript">// ... (Omitted for brevity) ...</code>
RxJS 的強大之處在於組合和操作資料流。這使我們能夠在業務邏輯到達元件之前對其進行處理,從而使元件保持清潔和可重複使用。
接下來,我們使用 Angular 的 CdkVirtualScrollViewport
設定元件來顯示內容。 一個方法處理視窗底部附近的滾動,透過 subRedditPage$
observable 取得下一頁。
<code class="language-typescript">// ... (Omitted for brevity) ...</code>
範本使用非同步管道訂閱query$
。 注意:隨著內容高度可變,虛擬捲軸變得更加複雜;為了提高效能,建議使用一致的物品高度。
<code class="language-html">// ... (Omitted for brevity) ...</code>
當使用者接近底部時,onScroll
方法會取得更多內容。它使用 nextPage
ID(來自 query$
)並發送到 subRedditPage$
,觸發下一個 API 呼叫並透過 query$
更新清單。
<code class="language-typescript">// ... (Omitted for brevity) ...</code>
搜尋列和選項卡控制項也整合在一起(下面的簡化範例)。
<code class="language-typescript">// ... (Omitted for brevity) ...</code>
這會創造一個幾乎無限的捲軸。 您可以在此處進行測試。 Reddit 的 API 有速率限制;你可能會在測試過程中碰到它們。 有關更多詳細信息,包括其他功能,請參閱 GitHub 存儲庫此處。
以上是使用 Angular 實作幾乎無限滾動的詳細內容。更多資訊請關注PHP中文網其他相關文章!