How to correctly render a list of up to 10000 elements.
Infinite drop-down loading technology allows users to scroll and view in front of a large number of blocks of content. This method is to keep loading new content as you scroll down.
When you use scrolling as the primary method of discovering data, it can allow your users to stay on the web page for longer and increase user engagement. With the popularity of social media, a large amount of data is consumed by users. Wireless scrolling provides an efficient way to allow users to browse massive amounts of information without having to wait for the page to be preloaded.
If we change our way of thinking, if there are 10,000 straight column components on a page, how can we use 5 components to dynamically render the entire page?
SolutionIn the optimization of long lists, we have many solutions, such as paging, lazy loading, etc. There is a very good interaction (Chrysanthemum Picture), so that the user can wait. This plan is also very successful.
How to find another way?
1. In the application of single pages, can we analyze the paging scheme once, with 10 elements per page, and 10 elements per page are rendered according to
2. Can we use a bracket to support the entire list length when the screen scrolls to the corresponding position and render the corresponding 10 elements
Flashing problemWhen we implement this idea, there will be a flickering problem. Since scrolling events are frequent, we find that the elements we see are constantly repainting, because we find which ten elements need to be rendered in each cutscene, and then replace them directly.
The idea here is that when I see the screen position, I will render 10 and then 10 upward and downward, with a total of 30. When controlling the rendering, I always replace the top or bottom elements, so that the part we can see in the middle will not be repainted and rendered. It's just that the pre-rendered data is being redrawn.
principleImplement a component that can display a list of n items with a fixed window size of 5 elements: that is, at any time, there are only 5 DOM containers on the infinite scroll n elements.
<ul> <li style=transform: translate3d(0px, 0px, 0px);>… </li> <li style=transform: translate3d(0px, 60px, 0px);>… </li> </ul>
For example: 100 elements, 5 are displayed on the home page. Initialization of [0,1,2,3,4] These 5 <li>s need to be rendered. When I scroll down a little, [1,2,3,4,5] these <li>s need to be rendered. At this time, do not directly replace the overall, only the difference terms should be replaced. The structure should be [5,1,2,3,4]. Since it is absolute positioning, it will be separated from the standard stream. A single redraw will not affect the other four, thereby improving performance.
How to implement it <!DOCTYPE html><html lang=en><head> <meta charset=UTF-8> <meta name=viewport content=width=device-width, initial-scale=1.0> <meta http-equiv=X-UA-Compatible content=ie=edge> <script src=https://cdn.bootcss.com/jquery/3.2.1/jquery.min.js></script> <title>Document</title> <style> body, ul, li { margin: 0; padding: 0; list-style: none; } ul { position: relative; } ul li { position: absolute; top: 0; width: 100%; height: 31px; line-height: 32px; border-bottom: 1px solid #ccc; } </style></head><body> <ul> </ul></body><script> // Total container var list = []; // Elements in the visual range var showList = []; // Render container var renderList = []; // Height of each container var lineHeight = 32 // Initialize 1000 elements for (var i = 0; i < 1000; i++) { list.push({ id: i, text: 'th' + (i + 1) + 'elements', top: i * lineHeight, bottom: (i + 1) * lineHeight }) } // Initialize container height $('ul').attr('style', 'height:' + 1000 * lineHeight + 'px') // Find the function render(top, bottom) of the initial container { showList = [] // Mark which data is repeated with the rendered after it is rendered, this part will not be rendered repeatedly var sameIndex = [] // Find out which element to scroll position var currentIndex = 0 for (var i = 0; i < list.length; i++) { var item = list[i] if (item.top <= window.scrollY && item.bottom > window.scrollY) { currentIndex = i; break; } } var range = 0 // Find the elements to be displayed up and down respectively in the currently found element, until the total number reaches 35 while (range < 100 && showList.length + sameIndex.length < 35) { if (currentIndex - range >= 0) { // Compare whether the elements that meet the conditions are in the rendered list, mark them when they are in the rendered list, and if they are not there, put them in the showList At that time, replace the unmarked element if (renderList.includes(list[currentIndex - range].id)) { // sameIndex.push(currentIndex-range) sameIndex.unshift(renderList.indexOf(list[currentIndex - range].id)) } else { showList.unshift(list[currentIndex - range]) } } } if (currentIndex + range < list.length && range != 0) { if (renderList.includes(list[currentIndex + range].id)) { sameIndex.push(renderList.indexOf(list[currentIndex + range].id)) } else { showList.push(list[currentIndex + range]) } } range++ } // Replace the new elements that need to be rendered with the render list elements that are not marked if (renderList.length > 0) { for (var i = 0; i < renderList.length; i++) { if (!sameIndex.includes(i) && showList.length) { renderList[i] = showList.shift().id $('ul li').eq(i).html(list[renderList[i]].id + list[renderList[i]].text).attr('style', 'transform: translate3d(0px, ' + list[renderList[i]].top + 'px, 0px);') } } } else { // Initialize the list for the first time renderList = showList.map(function (val) { return val.id }) renderList.map(function (key) { $('ul').append($('<li style=transform: translate3d(0px, ' + list[key].top + 'px, 0px);>#' + list[key].id + list[key].text + '</li>')) }) } console.log(renderList) } // First rendering render() $(window).scroll(function (e) { render() });</script></html> TODOKey points
The above is all the content of this article. I hope it will be helpful to everyone's learning and I hope everyone will support Wulin.com more.