资讯专栏INFORMATION COLUMN

百万数据如何在前端快速流畅显示?

Donne / 717人阅读

摘要:本文同步自我的博客园如果要在前端呈现大量的数据,一般的策略就是分页。为了解决这个问题,我们让数据是显示一部分,这一部分是可视区域的内容,以及上下各一屏一屏指的是高度所能容纳的区域大小的缓存内容。

本文同步自我的博客园:http://hustskyking.cnblogs.com

如果要在前端呈现大量的数据,一般的策略就是分页。前端要呈现百万数据,这个需求是很少见的,但是展示千条稍微复杂点的数据,这种需求还是比较常见,只要内存够,javascript 肯定是吃得消的,计算几千上万条数据,js 效率根本不在话下,但是 DOM 的渲染浏览器扛不住,CPU 稍微搓点的电脑必然会卡爆。

本文的策略是,显示三屏数据,其他的移除 DOM。

一、 策略

下面是我简单勾画的一个草图,我们把一串数据放到一个容器当中,这串数据的高度(Data List)肯定是比 Container 的高度要高很多的,如果我们一次性把数据都显示出来,浏览器需要花费大量的时间来计算每个 data 的位置,并且依次渲染出来,整个过程中 JS 并没有花费太多的时间,开销主要是 DOM 渲染。

                          /==============> Data List
        |     ....     | /
        +--------------+/
+=======|=====data=====|========+
|       +--------------+        |
|       |     data     |        |
|       +--------------+        |
|       |     data     |        | 
|       +--------------+        |  ======> Container
+=======|=====data=====|========+    
        +--------------+
        |     ....     |        Created By Barret Lee

为了解决这个问题,我们让数据是显示一部分,这一部分是 Container 可视区域的内容,以及上下各一屏(一屏指的是 Container 高度所能容纳的区域大小)的缓存内容。如果 Container 比较高,也可是只缓存半屏,缓存的原因是,在我们滚动滚动条的时候,js 需要时间来拼凑字符串(或者创建 Node ),这个时候浏览器还来不及渲染,所以会出现临时的空白,这种体验是相当不好的。

二、Demo

demo 在 IE 7、8 有 bug,请读者自己修复吧~

代码:

  1. 百万数据前端快速流畅显示
  2. item-0
    item-1
    item-2
    item-3
    item-4
    item-5
    item-6
    item-7
    item-8
    item-9
    item-10
    item-11
    item-12
    item-13
    item-14
    item-15
    item-99999
    item-99999

可以戳这个 demo,或者看这里 https://gist.github.com/barretlee/9744160

三、算法说明 1. 计算 start 和 end 节点

</>code

  1. | |
  2. +=======|==============|========+——
  3. | ↓——+--------------+ |
  4. | delta | | |
  5. | ↑——+--------------+ | height
  6. | | | |
  7. | +--------------+ |
  8. +=======|==============|========+——
  9. | |

Container 可以容纳的 Data 数目为 num = height / delta,Container 顶部第一个节点的索引值为

</>code

  1. var first = parseInt(Container.scrollTop / delta);

由于我们上下都有留出一屏,所以

</>code

  1. var start = Math.max(first - num, 0);
  2. var end = Math.min(first + num, len - 1);
2. 插入节点

通过上面的计算,从 start 到 end 将节点一次插入到 Container 中,并且将最后一个节点插入到 DOM 中。

</>code

  1. // 插入最后一个节点
  2. insert(len - 1);
  3. // 插入从 startend 之间的节点
  4. for(var s = start; s <= end; s++){
  5. var child = Container.children[s];
  6. // 如果 Container 中已经有该节点,或者该节点为最后一个节点则跳过
  7. if(!Container.contains(child) && s != len - 1){
  8. insert(s);
  9. }
  10. }

这里解释下为什么要插入最后一个节点,插入节点的方式是:

</>code

  1. function insert(i){
  2. var div = document.createElement("div");
  3. div.setAttribute("data-index", i);
  4. div.style.top = delta * i + "px";
  5. div.appendChild(document.createTextNode(data[i].content));
  6. Container.appendChild(div);
  7. }

可以看到我们给插入的节点都加了一个 top 属性,最后一个节点的 top 是最大的,只有把这个节点插入到 DOM 中,才能让滚动条拉长,让人感觉放了很多的数据。

3. 删除节点

为了减少浏览器的重排(reflow),我们可以隐藏三屏之外的数据。我这里为了方便,直接给删除掉了,后续需要再重新插入。

</>code

  1. while(child = Container.children[i++]){
  2. var index = child.getAttribute("data-index");
  3. // 这里记得不要把最后一个节点给删除掉了
  4. if((index > end || index < start) && index != len - 1){
  5. Container.removeChild(child);
  6. }
  7. }

当 DOM 加载完毕之后,触发一次 Container.onscroll(),然后整个程序就 OK 了。

四、小结

本文主要是叙述大数据加载的一点基本原理,程序可能有 bug,也有很多地方可以优化,了解下算法就行了。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/87501.html

相关文章

  • UCloud优刻得直播云ULive产品优势功能及架构示例

    摘要:优刻得直播云是为互联网直播应用提供超低延迟流畅高清高并发的整套解决方案。最终降低直播内容盗用风险及成本损失,提升客户合规性要求。UCloud优刻得直播云(ULive)是为互联网直播应用提供超低延迟、流畅高清、高并发的整套解决方案。包括实时转码,切片存储,分发加速,内容保护等核心功能。带给终端用户流畅的访问体验,简化相关部署运维工作,帮助视频直播业务快速上线。ULive产品页面https://...

    Tecode 评论0 收藏0
  • 如何打造线直播间(技术贴)

    摘要:背景当下视频直播如此红火,打造一个在线直播间涉及到哪些技术呢视频直播由主播的直播端以及观众的观看端组成。保持心跳断开重连快速搭建在线直播间按前文所述,搭建直播间有非常多的细节需要考虑,包括采集推流分发播放体验优化聊天室性能调优等。 背景 当下视频直播如此红火,打造一个在线直播间涉及到哪些技术呢? 视频直播由主播的直播端以及观众的观看端组成。一个简单的观看端最起码应包含播放器以及聊天室。...

    sugarmo 评论0 收藏0

发表评论

0条评论

Donne

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<