Loading [MathJax]/jax/output/CommonHTML/config.js
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >前端: 如何渲染十万条数据

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

作者头像
用户9914333
发布于 2022-07-22 06:58:39
发布于 2022-07-22 06:58:39
2.9K00
代码可运行
举报
文章被收录于专栏:bug收集bug收集
运行总次数:0
代码可运行

面试常见问题:

如何渲染十万条数据

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

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

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

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

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

01

直接渲染

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

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<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
代码运行次数:0
运行
AI代码解释
复制
<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
代码运行次数:0
运行
AI代码解释
复制
<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
代码运行次数:0
运行
AI代码解释
复制
<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 删除。

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

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
「前端进阶」高性能渲染十万条数据(时间分片)
在实际工作中,我们很少会遇到一次性需要向页面中插入大量数据的情况,但是为了丰富我们的知识体系,我们有必要了解并清楚当遇到大量数据时,如何才能在不卡主页面的情况下渲染数据,以及其中背后的原理。
ConardLi
2019/09/19
2.6K0
「前端进阶」高性能渲染十万条数据(时间分片)
一次加载1w条数据的最优解是什么?
如果你需要首屏快的话,要用分页,其中requestAnimationFrame分页更为优秀,因为这个api会是系统调用的,刷新时机和屏幕刷新保持一致。setTimeout则不能保证一致。
爱吃大橘
2022/12/27
5180
如何渲染几万条数据并不卡住界面?
如何在不卡住页面的情况下渲染数据,也就是说不能一次性将几万条 都渲染出来,而应该一次渲染部分 DOM,那么就可以通过 requestAnimationFrame 来 每 16 ms 刷新一次。
TimothyJia
2020/02/18
6530
如何渲染几万条数据并不卡住界面?
「前端进阶」高性能渲染十万条数据(虚拟列表)
在工作中,有时会遇到需要一些不能使用分页方式来加载列表数据的业务情况,对于此,我们称这种列表叫做 长列表。比如,在一些外汇交易系统中,前端会实时的展示用户的持仓情况(收益、亏损、收入等),此时对于用户的持仓列表一般是不能分页的。
桃翁
2019/11/05
11.4K2
「前端进阶」高性能渲染十万条数据(虚拟列表)
阿里前端高频面试题合集
做完这道题目,我们就需要格外注意,每个定时器的时间,并不是所有定时器的时间都为0哦。
helloworld1024
2022/09/13
4800
你必须懂的前端性能优化
对于 DNS 解析和 TCP 连接两个步骤,我们前端可以做的努力非常有限。相比之下,HTTP 连接这一层面的优化才是我们网络优化的核心。
张炳
2019/08/02
8300
你必须懂的前端性能优化
前端高频面试题(二)(附答案)
强缓存策略可以通过两种方式来设置,分别是 http 头信息中的 Expires 属性和 Cache-Control 属性。
helloworld1024
2022/08/30
3510
什么是时间分片(Time Slicing)?
所以为了避免这种情况,我们可以使用两种方案,一种是Web Worker,另一种是时间切片(Time Slicing)。
陈大鱼头
2020/09/21
1.5K0
什么是时间分片(Time Slicing)?
如何渲染几万条数据并不卡住界面
现在项目中列表页都会做成分页的形式,但是仍然存在一些场景:后端返回所有数据(可能成千上万条),前端渲染。下面提供几种解决思路。
Careteen
2022/02/14
7750
如何渲染几万条数据并不卡住界面
滴滴前端一面必会面试题汇总
这两种方式都是提高网页性能的方式,两者主要区别是一个是提前加载,一个是迟缓甚至不加载。懒加载对服务器前端有一定的缓解压力作用,预加载则会增加服务器前端压力。
hellocoder2029
2022/09/13
5470
前端常见手写面试题
明明我只改变了s1的play属性,为什么s2也跟着变了呢?很简单,因为两个实例使用的是同一个原型对象
helloworld1024
2022/12/12
4130
前端手写面试题,看这一篇就够了
题目描述:有一组版本号如下 ['0.1.1', '2.3.3', '0.302.1', '4.2', '4.3.5', '4.3.4.5']。现在需要对其进行排序,排序的结果为 ['4.3.5','4.3.4.5','2.3.3','0.302.1','0.1.1']
helloworld1024
2022/11/14
3870
有哪些前端面试题是面试官必考的_2023-02-27
这时候就需要使用虚拟列表了 大家自行百度哈 虚拟列表和虚拟表格在日常项目使用还是很频繁的
var_1024
2023/02/27
7520
腾讯前端必会面试题
因为 JS 采用 IEEE 754 双精度版本(64位),并且只要采用 IEEE 754 的语言都有该问题。
yyds2026
2022/09/13
5240
【优化】356- 你必须懂的前端性能优化
对于 DNS 解析和 TCP 连接两个步骤,我们前端可以做的努力非常有限。相比之下,HTTP 连接这一层面的优化才是我们网络优化的核心。
pingan8787
2019/09/24
7320
【优化】356- 你必须懂的前端性能优化
做了一份前端面试复习计划
以下是代码实现,实现了思路,但是可能会存在 Bug,但是这种设计题一般是给出设计思路和部分代码,不会需要写出一个无问题的代码
loveX001
2022/12/08
4250
2022前端常考手写面试题总结
此方法属于黑魔法,极易容易被xss攻击,还有一种new Function大同小异。
helloworld1024
2022/11/10
4900
如果后端API一次返回10万条数据,前端应该如何处理?
最近,我的一位朋友在面试时被问到这个问题。这个问题其实是考察面试者对性能优化的理解,涉及的话题很多。下面我就和大家一起来分析一下这个问题。 创建服务器 为了方便后续测试,我们可以使用node创建一个简单的服务器。 服务器端代码: const http = require('http') const port = 8000; let list = [] let num = 0 // create 100,000 records for (let i = 0; i < 100_000; i++) {   n
程序猿DD
2022/06/16
1.6K0
如果后端API一次返回10万条数据,前端应该如何处理?
滴滴前端面试题(边面边更)_2023-02-24
柯里化(currying) 指的是将一个多参数的函数拆分成一系列函数,每个拆分后的函数都只接受一个参数。
java_js0166293
2023/02/24
1.3K0
那些年面挂的js手写题
arr = {a:1, b:3}, {a:2, b:3, c:4}, {a:3},求和
helloworld1024
2022/11/07
8270
相关推荐
「前端进阶」高性能渲染十万条数据(时间分片)
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验