业务中不一定会遇到,但是面试时可能会遇到的问题很大,前端如何在保证页面渲染性能的前提下,一次性渲染百万条后端数据!!合不合理我们先不评论,具体就说下前端js怎么实现!!
时间分片,把大量的数据分成一段段的,进行分时加载,但是不影响用户的体验。
基础版
let ul = document.getElementById('container');
const total = 1000000 // 总数据条数
let once = 20 // 每次渲染条数
let page = total / once // 需要渲染的总次数
let index = 0 // 每条记录的索引,防止数据丢失或没有渲染到最后一条// 两个参数:剩余需要渲染的数据条数,当前渲染的索引
function timeSilceAdd(curTotal, curIndex) { let pageCount = Math.min(once, curTotal) // 每次渲染开始的条数索引setTimeout(() => {for (let i = 0; i < pageCount; i++) {let li = document.createElement('li');li.innerText = curIndex + i + ':' + ~~(Math.random() * total); ul.appendChild(li);}// console.log('9999')if(curTotal - pageCount <= 0) return console.log('end')timeSilceAdd(curTotal - pageCount, curIndex + pageCount)})
}timeSilceAdd(total, index)
上面的用的setTimeout
,有可能有性能问题,加载的时候,和其他业务加载有可能会导致阻塞,卡顿。下面,我们用requestAnimationFrame
来优化性能。
优化版
function timeSilceAdd2(curTotal, curIndex) {let pageCount = Math.min(once, curTotal) // 每次渲染开始的条数索引requestAnimationFrame(() => {const fr = document.createDocumentFragment()for (let i = 0; i < pageCount; i++) {let li = document.createElement('li');li.innerText = curIndex + i + ':' + ~~(Math.random() * total); fr.appendChild(li)}ul.appendChild(fr)console.log('9999')if(curTotal - pageCount <= 0) return console.log('end')timeSilceAdd2(curTotal - pageCount, curIndex + pageCount)})}timeSilceAdd2(total, index)