Efficient Rendering of Large Lists (Virtual Lists)
- 文章發表於
Have you ever encountered scenarios in your projects where you need to render large lists, such as large data tables or simple but numerous data items that need to be listed? The author recalls facing a similar issue in their first job, where they directly used map
to render a list of over ten thousand data items, only to find the page became extremely sluggish or even crashed. The main reason was that rendering over ten thousand data items into the DOM at once would cause the browser to spend a significant amount of time rendering these elements, and during interaction, the page would become very sluggish due to repaint/reflow.
This article will introduce the principle of virtual lists and how to implement them.
What is a Virtual List
Whether browsing data on a computer or a mobile phone, there is a maximum height, and it's unnecessary to render all data into the DOM at once. Virtual lists primarily solve the above problem, with the core concept being to only render the data currently needed in the viewport. Thus, only a small number of elements are rendered each time, while also simulating the total height of the list's data. This allows for rendering only the data in the current viewport while achieving an effect similar to infinite scrolling. As users scroll the list, new items entering the visible range are loaded in real-time, and old items leaving the visible range are removed.
Through the interactive effect above, you can better understand the principle behind it. By setting the number of data items and the height of each item, you can simulate the relationship between the viewable area and the entire list by sliding the Scroll Position. Assuming the viewable area only has space for 10 items, even if there are 100 items in total, only 10 items need to be rendered, and the remaining 90 items are presented through simulation, achieving an effect similar to infinite scrolling.
<div style="height: 500px; overflow: auto;"><div style="height: 500000px;"></div></div>
Implementing a Virtual List
From the interactive UI above, it's clear that the most important aspect of implementing a virtual list is knowing the start and end points of the viewable area, which are startIndex
and endIndex
, respectively. Their calculation methods are as follows:
const startIndex = Math.floor(scrollTop / itemHeight);const visibleItemCount = Math.ceil(containerHeight / itemHeight);const endIndex = startIndex + visibleItemCount;
Next, it's necessary to calculate the actual position of each item to know its position in the list:
const itemPosition = itemIndex * itemHeight;
After obtaining the start and end points of the viewable area and the actual position of each item from the above calculations, the next step is to calculate the total height of all data:
const totalHeight = itemCount * itemHeight;
A final small trick is to use overscan to optimize the rendering of the list, which involves rendering areas outside the viewable area as well. This avoids the list jumping when scrolling due to areas outside the viewable area not being rendered.
const overscanCount = 3;const startWithOverscan = Math.max(0, startIndex - overscanCount);const endWithOverscan = Math.min(itemCount - 1, endIndex + overscanCount);
Finally, we just need to add an onScroll
event to the parent layer and update scrollTop
in the event to implement a very basic virtual list.
Conclusion
Although the above implementation cannot be used in a production environment, it provides a basic understanding of the principle behind virtual lists. For using virtual lists in a production environment, it is recommended to use libraries such as react-window or tanstack-virtual.