数据量太大,DOM节点加载过多,怎么保证前端在渲染的时候页面不会卡(性能优化)
一、定时器分批渲染
既然一次渲染10万条数据会造成页面加载速度缓慢,那么我们可以不要一次性渲染这么多数据,而是分批次渲染, 比如一次10000条,分10次来完成, 这样或许会对页面的渲染速度有提升。 然而,如果这13次操作在同一个代码执行流程中运行,那似乎不但无法解决糟糕的页面卡顿问题,反而会将代码复杂化。 类似的问题在其它语言最佳的解决方案是使用多线程,JavaScript虽然没有多线程,但是setTimeout和setInterval两个函数却能起到和多线程差不多的效果。 因此,要解决这个问题, 其中的setTimeout便可以大显身手。 setTimeout函数的功能可以看作是在指定时间之后启动一个新的线程来完成任务。
1 function loadAll(response) { 2 //将10万条数据分组, 每组500条,一共200组 3 var groups = group(response); 4 for (var i = 0; i < groups.length; i++) { 5 //闭包, 保持i值的正确性 6 window.setTimeout(function () { 7 var group = groups[i]; 8 var index = i + 1; 9 return function () { 10 //分批渲染 11 loadPart( group, index ); 12 } 13 }(), 1); 14 } 15 } 16 17 //数据分组函数(每组500条) 18 function group(data) { 19 var result = []; 20 var groupItem; 21 for (var i = 0; i < data.length; i++) { 22 if (i % 500 == 0) { 23 groupItem != null && result.push(groupItem); 24 groupItem = []; 25 } 26 groupItem.push(data[i]); 27 } 28 result.push(groupItem); 29 return result; 30 } 31 var currIndex = 0; 32 //加载某一批数据的函数 33 function loadPart( group, index ) { 34 var html = ""; 35 for (var i = 0; i < group.length; i++) { 36 var item = group[i]; 37 html += "<li>title:" + item.title + index + " content:" + item.content + index + "</li>"; 38 } 39 //保证顺序不错乱 40 while (index - currIndex == 1) { 41 $("#content").append(html); 42 currIndex = index; 43 } 44 }
二、document.createDocumentFragment()
用来创建一个虚拟的节点对象,节点对象不属于文档树。
当需要添加多个DOM元素时,可以先把DOM添加到这个虚拟节点中。然后再统一将虚拟节点添加到页面,这会减少页面渲染DOM的次数。
window.requestAnimationFrame
接受参数为函数,比起setTimeout和setInterval有以下优点:
1.把每一帧中的所有DOM操作集中起来,在一次的重排/重绘中完成。每秒60帧。
2.在隐藏或者不可见的元素中,requestAnimationFrame将不会重绘/重排。
1 <!DOCTYPE html> 2 <html lang="en"> 3 4 <head> 5 <meta charset="UTF-8"> 6 <meta http-equiv="X-UA-Compatible" content="IE=edge"> 7 <meta name="viewport" content="width=device-width, initial-scale=1.0"> 8 <title>Document</title> 9 </head> 10 <body> 11 <ul></ul> 12 <script> 13 //总数据 14 const total = 1000000; 15 //每次插入的数据 16 const once = 20; 17 //需要插入的次数 18 const times = Math.ceil(total / once) 19 //当前插入的次数 20 let curTimes = 0; 21 //需要插入的位置 22 const ul = document.querySelector('ul') 23 function add() { 24 let frag = document.createDocumentFragment() 25 for (let i = 0; i < once; i++) { 26 let li = document.createElement('li') 27 li.innerHTML = Math.floor(i + curTimes * once) + 'asdjflkjasdlfkjdalksjkaflds' 28 frag.appendChild(li) 29 } 30 curTimes++; 31 ul.appendChild(frag) 32 if (curTimes < times) { 33 window.requestAnimationFrame(add) 34 } 35 } 36 window.requestAnimationFrame(add) 37 </script> 38 </body> 39 </html>