前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >前端: 如何渲染十万条数据

前端: 如何渲染十万条数据

作者头像
用户9914333
发布2022-07-22 14:58:39
2.7K0
发布2022-07-22 14:58:39
举报
文章被收录于专栏:bug收集bug收集

面试常见问题:

如何渲染十万条数据

最直接的方法就是直接渲染出来,但是这样的做法肯定是不可取的,因为直接渲染太耗性能了。

提高渲染性能的解决方案有如下:

  • 虚拟列表(也叫按需渲染或可视区域渲染)
  • 时间分片

虚拟列表是最主流的解决方案,不渲染所有的数据,只渲染可视区域中的数据。当用户滑(滚)动时,通过监听 scroll 来判断是上滑还是下拉,从而更新数据。同理 IntersectionObserver 和 getBoundingClientRect 都能实现

时间分片主要是分批渲染DOM,使用 requestAnimationFrame 来让动画更加流畅

01

直接渲染

通过for 直接渲染,太消耗性能

代码语言:javascript
复制
<ul id="container"></ul>
// 记录任务开始时间
let now = Date.now();
// 插入十万条数据
const total = 100000;
// 获取容器
let ul = document.getElementById('container');
// 将数据插入容器中
for (let i = 0; i < total; i++) {
let li = document.createElement('li');
    li.innerText = (Math.random() * total)
    ul.appendChild(li);
}

console.log('JS运行时间:',Date.now() - now);
setTimeout(()=>{
console.log('总运行时间:',Date.now() - now);
},0)

0 2

虚拟列表

只渲染可视区域中的数据, 可以通过scroll 或IntersectionObserver(交叉观察者,异步的,性能消耗小) 和 getBoundingClientRect 都可以使用

注意:区分虚拟列表与懒加载

懒加载与虚拟列表其实都是延时加载的一种实现,原理相同但场景略有不同

  • 懒加载的应用场景偏向于网络资源请求,解决网络资源请求过多时,造成的网站响应时间过长的问题。
  • 虚拟列表是对长列表渲染的一种优化,解决大量数据渲染时,造成的渲染性能瓶颈的问题。

03

时间分片

方法一:使用 setTimeout

页面的卡顿是由于同时渲染大量DOM所引起的,所以我们考虑将渲染过程分批进行,可以使用setTimeout来实现分批渲染

代码语言:javascript
复制
<ul id="container"></ul>
//需要插入的容器
let ul = document.getElementById('container');
// 插入十万条数据
let total = 100000;
// 一次插入 20 条
let once = 20;
//总页数
let page = total/once
//每条记录的索引
let index = 0;
//循环加载数据
function loop(curTotal,curIndex){
if(curTotal <= 0){
return false;
    }
//每页多少条
let pageCount = Math.min(curTotal , once);
setTimeout(()=>{
  for(let i = 0; i < pageCount; i++){
              let li = document.createElement('li');
              li.innerText = curIndex + i + ' : ' + ~~(Math.random() * total)
              ul.appendChild(li)
          }
          loop(curTotal - pageCount,curIndex + pageCount)
  },0)
}
loop(total,index);

此方法可以使用页面加载的时间变快,但是当我们快速滚动页面的时候,会发现页面出现闪屏或白屏的现象

为什么会出现闪屏现象呢

大多数电脑显示器的刷新频率是60Hz,大概相当于每秒钟重绘60次;大多数电脑显示器的刷新频率是60Hz,大概相当于每秒钟重绘60次

大多数浏览器都会对重绘操作加以限制,不超过显示器的重绘频率,因为即使超过那个频率用户体验也不会有提升。

setTimeout的执行时间并不是确定的,当 setTimeout 的执行步调和屏幕的刷新步调不一致,就会出现丢帧的情况,从而出现闪屏

方法二:requestAnimationFrame

与setTimeout相比,requestAnimationFrame最大的优势是由系统来决定回调函数的执行时机,换句话说就是,requestAnimationFrame的步伐跟着系统的刷新步伐走。它能保证回调函数在屏幕每一次的刷新间隔中只被执行一次,这样就不会引起丢帧现象。

代码语言:javascript
复制
<ul id="container"></ul>
//需要插入的容器
let ul = document.getElementById('container');
// 插入十万条数据
let total = 100000;
// 一次插入 20 条
let once = 20;
//总页数
let page = total/once
//每条记录的索引
let index = 0;
//循环加载数据
function loop(curTotal,curIndex){
if(curTotal <= 0){
return false;
    }
//每页多少条
let pageCount = Math.min(curTotal , once);
window.requestAnimationFrame(function(){
    for(let i = 0; i < pageCount; i++){
            let li = document.createElement('li');
            li.innerText = curIndex + i + ' : ' + ~~(Math.random() * total)
            ul.appendChild(li)
        }
        loop(curTotal - pageCount,curIndex + pageCount)
    })
}
loop(total,index);

方法三:文档碎片 + requestAnimationFrame

我们还可以DOM操作上去优化,通过 DocumentFragment(文档碎片 )添加节点。

DocumentFragments是DOM节点,但并不是DOM树的一部分,可以认为是存在内存中的,所以将子元素插入到文档片段时不会引起页面回流。

可以将要渲染的节点,添加到碎片节点中,然后再将碎片节点,添加到DOM树中,从而提高性能 。

代码语言:javascript
复制
<ul id="container"></ul>
//需要插入的容器
let ul = document.getElementById('container');
// 插入十万条数据
let total = 100000;
// 一次插入 20 条
let once = 20;
//总页数
let page = total/once
//每条记录的索引
let index = 0;
//循环加载数据
function loop(curTotal,curIndex){
if(curTotal <= 0){
return false;
    }
//每页多少条
let pageCount = Math.min(curTotal , once);
window.requestAnimationFrame(function(){
    let fragment = document.createDocumentFragment();
    for(let i = 0; i < pageCount; i++){
            let li = document.createElement('li');
            li.innerText = curIndex + i + ' : ' + ~~(Math.random() * total)
            fragment.appendChild(li)
        }
        ul.appendChild(fragment)
        loop(curTotal - pageCount,curIndex + pageCount)
    })
}
loop(total,index);
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2022-04-28,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 bug收集 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 为什么会出现闪屏现象呢
相关产品与服务
容器服务
腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档