天天看點

譯文:增強在 React 中渲染大型清單的方式

譯文:增強在 React 中渲染大型清單的方式

介紹

在 React 中渲染大型清單對于開發人員來說可能是一項艱巨的任務。随着清單大小的增加,DOM(文檔對象模型)樹也會增長,進而導緻渲染速度慢、滾動不流暢和記憶體使用率高等性能問題。在本文中,我們将讨論開發人員在渲染大型清單時面臨的一些常見問題,以及可用于克服這些問題的各種解決方案。

問題陳述

為什麼在 Web 浏覽器中渲染大量清單是一項艱巨的任務?嗯,在渲染大量項目清單時需要考慮幾個因素。首先是性能,随着螢幕上要渲染的元素數量增加,浏覽器的渲染引擎開始遇到性能問題。這會導緻渲染速度變慢,進而導緻使用者界面遲緩和使用者體驗不佳。

處理大量元素清單需要耗費大量計算資源。滾動浏覽大型清單可能會讓最終使用者感到不爽,最糟糕的情況是,他們可能會看到一個完全無響應的頁面。由于處理能力和記憶體有限,對手機等低端裝置的負面影響會更大。

考慮到所有這些問題,作為軟體開發人員,我們需要采用優化技術并選擇适當的政策。

概括

本文主要讨論如何在 React 中渲染大量清單。首先,我們将定義大量清單的含義。然後,我們将研究一些可以采用的解決方案,以解決問題陳述中指出的問題。最後,我們将讨論在浏覽器中渲染大量清單時需要牢記的幾個關鍵事項。

龐大的清單是什麼意思呢?

譯文:增強在 React 中渲染大型清單的方式

圖 1:渲染大量清單的代碼片段

龐大清單的定義是動态的。它完全取決于最終使用者的裝置。如果他們都在高端計算機或移動裝置上,那麼在看到任何性能限制之前,您可以在頁面上安全呈現的元素數量将非常高。

另一方面,如果您的最終使用者的裝置比較普通,記憶體和處理能力有限,則此門檻值将小于上述門檻值。随着現代浏覽器的進步,您可以輕松加載大量 DOM 元素而不必擔心太多,但即便如此,如果您開始渲染包含 1,000 行或更多行的訂單清單,您可以認為它是巨大的。

如何解決 React 中渲染大型清單的問題?

如果您最終需要渲染數以萬計的複雜清單項,則無論最終使用者的硬體性能如何,您都不可避免地必須使用以下解決方案之一。首先,我們将從每個人都可以合并到其代碼中的通用解決方案開始:

保持渲染樹較小

譯文:增強在 React 中渲染大型清單的方式

圖 2:渲染樹圖解

總體而言,保持精簡的渲染樹可以提高整體性能,因為 DOM 元素越多,浏覽器需要配置設定的空間就越多。此外,浏覽器在布局階段将花費更多時間。這在渲染大量清單時變得極為關鍵。即使減少一個 div 也能帶來明顯的性能差異。

最佳做法是使用最少數量的 DOM 元素來建立清單項,而不影響設計。

讓我們來實驗一下:

首先,我們将建立一個包含約 10,000 個元素的簡單清單。以下是該清單的代碼沙箱。

讓我們來看看該頁面的 Lighthouse 性能:

譯文:增強在 React 中渲染大型清單的方式

圖 3:海量清單的 Lighthouse 評分

首次内容繪制 0.9 秒
最大的内容豐富的油漆 3.0 秒
總阻塞時間 2.1 秒
總績效得分 43

現在,讓我們向清單項中添加一個 div 并擷取所有性能數字。

以下是燈塔的表演:

譯文:增強在 React 中渲染大型清單的方式

圖 4:帶有一個額外 div 的 Lighthouse 分數

首次内容繪制 1 秒
最大的内容豐富的油漆 3.3 秒
總阻塞時間 3.3 秒
總績效得分 40

無限滾動

現在讓我們進入實際的解決方案,其中第一個是使用無限滾動技術。用更簡單的話來說,這種技術意味着隻渲染填滿整個頁面長度所需的清單項,然後在使用者向下滾動時添加更多項目。

我們可以使用react-infinite-scroller庫來實作這一點。

以下是使用 react-infinite-scroller 實作的相同 10,000 個項目清單。

讓我們看看它是如何影響我們的表現的:

譯文:增強在 React 中渲染大型清單的方式

圖 5:無限滾動的 Lighthouse 得分

首次内容繪制 1.0 秒
最大的内容豐富的油漆 2.5 秒
總阻塞時間 160毫秒
總績效得分 78

我們的整體績效滾動從基數43躍升至78,這是一個巨大的進步。

這是因為我們實際上将清單分成了很小的部分。我們不是一次性渲染所有 10,000 個項目,而是隻渲染在使用者視圖中渲染頁面部分所需的前幾個項目。當使用者向下滾動時,react-infinite-scroller 庫會将更多項目添加到 DOM。

視窗化

解決該問題的另一個方法是使用視窗技​術。

視窗化(或虛拟化)是一種技術,您可随時僅渲染清單中使用者可見的部分。與無限滾動不同,在視窗化中,DOM 始終具有恒定數量的元素。換句話說,我們僅渲染填充使用者視野所需的元素,并從清單頂部和底部移除尚未出現在視圖中的元素。

譯文:增強在 React 中渲染大型清單的方式

圖 6:視窗技術圖示

當清單中的每個項目都有固定高度時,視窗化會大放異彩。這樣,就可以根據滾動情況輕松計算出需要從 DOM 中添加或删除哪些項目。此外,無論使用者滾動到哪裡,頁面的記憶體使用量都會保持不變,因為 DOM 元素的數量保持不變。

以下是使用 react-window 實作的相同 10,000 個項目清單。

讓我們看看它是如何影響我們的表現的:

譯文:增強在 React 中渲染大型清單的方式

圖 7:帶視窗的海量清單的 Lighthouse 得分

首次内容繪制 1.0 秒
最大的内容豐富的油漆 2.5 秒
總阻塞時間 190毫秒
總績效得分 76

要記住的關鍵事項

使用這兩種技術,您都無法執行浏覽器搜尋。換句話說,如果使用者使用cmd + f搜尋尚未呈現的文本,他們将看到 0 個比對項(共 0 個)。為了防止這種情況,您應該在清單中添加自定義搜尋或過濾選項。

與本機滾動相比,在 DOM 中添加/删除元素總是會出現輕微的延遲,但這仍然比您的應用程式最終因大量 DOM 元素而挂起要好。

建立您自己的解決方案

如果您希望保持解決方案輕量并且不想使用任何庫,您還可以使用Intersection Observer API實作自己的 DOM 元素延遲加載。

首先,添加足夠的元件來填充您的視口。使用 getBoundingClientRect 擷取視口高度,并将其除以近似的最小項目高度。為此計數加 1 以獲得更好的結果。現在在其下方添加一個虛拟元件(此元件不需要顯示任何内容;它隻需要存在于清單的底部)。将交集可觀察對象附加到此元件,并且每當此元件在視圖中時,将更多項目添加到清單中以在 DOM 中呈現。這樣,您最終将開發一個簡單的無限滾動解決方案。

結論

現在,您應該能夠處理 React 應用程式中的大型清單。簡而言之,您應該一次隻渲染清單的一小部分,并確定視圖中有足夠的過濾器供使用者對清單進行篩選。

作者:

Srijan Gulati

Srijan Gulati is a Senior Software Developer and the Frontend lead for Uber’s Crash analytics (Apps, services, and in-app bug reporter). He is passionate about responsive and accessible UX, problem-solving, and VIM.

Karan Verma

Karan Verma is a Senior Software Engineer and Frontend Developer specializing in data visualization at scale.

出處:https://www.uber.com/en-JP/blog/supercharge-the-way-you-render-large-lists-in-react/