Topic: An array of 10w records is rendered to the page at one time. How can I avoid freezing the UI?
There is an empty unordered list node on the page ul
, which id
is list-with-big-data
, now need to insert 10w into the li
list, the text content of each list item can be defined by yourself, and when each li
is clicked, it is required to alert
display the text in the list item by displaying content.
<!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"> <title>The page loads massive data</title> </head> <body> <ul id="list-with-big-data">100000 数据</ul> <script> // Add your code logic here </script> </body> </html>
Analysis: We can reduce the blocking time of the main thread from two aspects: reducing the number of DOM operations and shortening the cycle time.
It can be DocumentFragment
used to reduce the number of DOM operations and reduce the impact of reflow on performance.
li
In terms of shortening the cycle time, we can insert 100,000 batches into the page through the divide and conquer idea, and we do this by requestAniminationFrame
inserting new nodes before the page is redrawn.
(function() { const ulContainer = document.getElementById("list-with-big-data"); // defensive programming if (! ulContainer) { return ; } const total = 100000 ; // The total number of inserted data const batchSize = 4 ; // The number of nodes inserted in each batch, the more the number, the more stuck the interface const batchCount = total / batchSize; // The number of batches let batchDone = 0 ; // Number of completed batches function appendItems() { // Use DocumentFragment to reduce the number of DOM operations, and do not reflow existing elements const fragment = document.createDocumentFragment(); for (let i = 0; i < batchSize; i++) { const liItem = document.createElement("li"); liItem.innerText = batchDone * batchSize + i + 1 ; fragment.appendChild(liItem); } // Only modify the DOM once per batch ulContainer.appendChild(fragment); batchDone++; doAppendBatch(); } function doAppendBatch() { if (batchDone < batchCount) { // Insert new nodes in batches before redrawing window.requestAnimationFrame(appendItems); } } // kickoff doAppendBatch(); // Using event delegation and JavaScript's event mechanism to monitor massive elements and effectively reduce the number of event registrations ulContainer.addEventListener( " click " , function(e) { const target = e.target; if (target.tagName === "LI") { alert(target.innerText); } }); })();