业务中不一定会遇到,但是面试时可能会遇到的问题很大,前端如何在保证页面渲染性能的前提下,一次性渲染百万条后端数据!!合不合理我们先不评论,具体就说下前端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)