首页 > 其他分享 >如果后端返回上万条数据,前端如何渲染成长列表呢?

如果后端返回上万条数据,前端如何渲染成长列表呢?

时间:2023-10-29 20:11:18浏览次数:31  
标签:渲染 上万条 高度 列表 索引 区域 可视区

使用虚拟列表

     只对可见区域进行渲染,对非可见区域中的数据不渲染或部分渲染的技术,从而达到极高的渲染性能,虚拟列表其实是按需显示的一种实现。

     虚拟列表一般包含三个组成部分:可视区域、列表渲染区域、真实列表区域。列表渲染区大于等于可视区。比如容器区域需要渲染三屏的节点,当前展示区上一页下一页,滚动过程中会更流畅

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

视图结构

   按照图示,我们先构造如下的视图结构

    1. viewport:可视区域的容器

    2. list-phantom:容器内的占位,高度为真实列表区域的高度,用于形成滚动条

    3. list-area:列表项的渲染区域

<div className="viewport"> 
    <div className="list-phantom"></div> 
    <div className="list-area"> 
        <!-- item-1 --> 
        <!-- item-2 --> 
        <!-- item-n --> 
    </div>
</div>

基本思路

    虚拟列表的核心思路是 处理用户滚动时可视区域数据的显示可视区外数据的隐藏,这里为了方便说明,引入以下相关变量:

     1. startIndex:可视区域的开始索引

     2. endIndex:可视区域的结束索引

     3. startOffset:可视区第一个元素的向上偏移量

   当用户滚动列表时:

    1. 计算可视区域的 开始索引 和 结束索引

    2. 根据 开始索引 和 结束索引 渲染数据

    3. 计算 第一个元素 偏移量并设置到列表渲染区

 

  具体计算:

  先假定每个列表项的高度固定为100px,则我们可设置和推导出:

     1. 列表项高度: itemSize = 100

     2. 可视区的列表项数量: viewcount = viewport / itemSize

     3. 可视区结束索引 :endIndex = startIndex + viewcount

  当用户滚动时,逻辑处理如下:

     1. 获取可视区滚动距离 scrollTop;

     2. 根据 滚动距离 scrollTop 和 单个列表项高度 itemSize 计算出 开始索引 startIndex 和 结束索引 endIndex;

  // 获取startIndex 
  const getStartIndex = (scrollTop) => { 
     return Math.floor(scrollTop / itemSize); // 这里可以思考下,为什么要用 Math.floor 
  };

     3. 根据 开始索引  和 单个列表项高度  计算出 可视区第一个元素的向上偏移量 ;

     4. 只显示 开始索引  和 结束索引  之间的列表项;

     5. 设置 列表渲染区域 list-area 的偏移量为 startOffset

 

动态高度

   以上是列表项高度固定的情况,实际项目中列表项高度通常可能是有图文视频在内,高度不固定,我们可以在内容渲染完成后,获得其高度

   1. 构造一个数组,缓存列表每行高度及距离顶部及底部高度

   2. 动态计算鼠标滑动时当前应展示的列表区间

   3. 在dom节点插入后再计算当前显示的节点实际高度替换缓存中的高度修改可视化位置距离顶部距离

当有 item 项高度变化后,我们只需要维护这一个数组的数据即可,从而大大减少了处理起来的复杂度。

使用 ResizeObserver 可以监听到指定元素的高度的变化。ResizeObserver可以监听到指定元素的高度的变化,而且是原生浏览器层面的支持,性能方面也是可靠的。兼容性方面,除了IE,其他也都是支持的。

 

缺点

 虚拟列表也不是十全十美的,它会有一些问题,主要是:

   1. 滚动过快出现会白屏

    2. 滚动时有大量的计算

白屏优化

方案一:增加缓存区

在虚拟列表的原理中有提到过,列表渲染区是可以大于等于可视区,这里的采取措施就是列表渲染区域要大于可视区。

措施:在可视区外设置缓存区,额外渲染合适的列表项。

优势:在滚动过快时,会先显示缓存区中的元素,减少白屏出现的情况。

不足:缓存区域设置过大,也会导致渲染性能变差,需要结合具体的业务场景设置合适的缓存值。

方案二:部分渲染

在前面虚拟列表的原理中也有提到过,对非可见区域中的数据不渲染或部分渲染的技术,这里所用到的就是不可见列表项的部分渲染。

措施:采用skeleton加载骨架屏来代替原有的不渲染部分,这样当滚动过快时,白屏也就替换为了加载屏。

优势:用户体验上会有所增强。

不足:会额外渲染skeletondom元素。不过对比整个列表元素的dom节点来看,可以忽略不计的。

 

计算优化

我们可以采用二分查找法来进行优化

 

原文章:

https://zhuanlan.zhihu.com/p/444778554

https://blog.csdn.net/weixin_48403384/article/details/123325706

 

标签:渲染,上万条,高度,列表,索引,区域,可视区
From: https://www.cnblogs.com/buluzombie/p/17796334.html

相关文章

  • 【Qt6】列表模型——几个便捷的列表类型
    前面一些文章,老周简单介绍了在Qt中使用列表模型的方法。很明显,使用ItemModel在许多时候还是挺麻烦的——要先建模型,再放数据,最后才构建视图。为了简化这些骚操作,Qt提供了几个便捷类。今天咱们逐个看看。一、QListWidget 这厮对应的ListView,用来显示简单的列表。要添加列......
  • 列表包裹元组,指定元组中数字大小排序字段operator用法
    importoperatorsomelist=[(1,5,8),(6,2,4),(9,7,5)]somelist.sort(key=operator.itemgetter(0))print(somelist)#[(1,5,8),(6,2,4),(9,7,5)]somelist.sort(key=operator.itemgetter(1))print(somelist)#[(6,2,4),(1,5,8),(9,7,5)]somelist.sor......
  • MFC---常用控件(下)(列表控件、树控件、标签控件)
    列表控件CListCtrl常用属性设置:view->Report(报表方式)常用接口关联控件变量后,测试接口://设置风格样式 //LVS_EX_GRIDLINES网格 //LVS_EX_FULLROWSELECT选中整行 m_list.SetExtendedStyle(m_list.GetExtendedStyle() |LVS_EX_GRIDLINES|LVS_EX_FULLROWSELECT); //插......
  • Transformer 相关资料列表
    Transformer相关资料列表Encoder-Decoder框架1Transformer模型1连续词袋模型(CBOW)Word2vecTransformer模型中的positionalencoding(位置编码)计算理解Transformer模型中的positionalencoding(位置编码)计算理解(2)self-attention自注意力机制注意力机制(2)self-at......
  • 访问控制列表
    核心华为路由器访问控制列表默认的过滤模式是()。A.拒绝B.允许C.必须配置D.空思科路由器访问控制列表默认的过滤模式是()A.拒绝B.允许C.必须配置D.空命令解析aclnumber2000 rule5permitsource20.1.1.10 rule10deny 特别注意:需要将允许的全部的写在前面,最后追加一条......
  • Python根据列表在指定目录寻找对应前缀的文件
    现在有一个txt列表,里面包含的是一些文件名,如a,b等等,现在需求是在一个多级文件夹下,需要寻找以a为名字的任何格式文件,如a.001,a.002等等,寻找这个txt列表里包含的文件名的对应文件,复制到指定文件夹下importosimportshutil#读取文件名列表withopen('msg.txt','r')asfile:......
  • python基于动态数量个列表求笛卡尔积
    需求有N个list,分别是listA,listB,listC。。。等等,N的数量不确定,现在对这些list的所有可能组合的值求笛卡尔积,比如(listA,listB),(listA,listC),(listB,listC),(listA,listB,listC)。。。求这里每个组合的笛卡尔积。分析对实现以上需求,可分解为2个部分:1.求所有list的组合2.对所......
  • Kubernetes 中使用consul-template渲染配置
    Kubernetes中使用consul-template渲染配置当前公司使用consul来实现服务发现,如Prometheue配置中的target和alertmanager注册都采用了consul服务发现的方式,以此来灵活应对服务的变更。但对于其他服务,是否也有一个通用的方式来使用consul管理配置文件?本文中描述如何使用consul-tem......
  • 循序渐进介绍基于CommunityToolkit.Mvvm 和HandyControl的WPF应用端开发(5) -- 树列表
    在我们展示一些参考信息的时候,有所会用树形列表来展示结构信息,如对于有父子关系的多层级部门机构,以及一些常用如字典大类节点,也都可以利用树形列表的方式进行展示,本篇随笔介绍基于WPF的方式,使用TreeView来洗实现结构信息的展示,以及对它的菜单进行的设置、过滤查询等功能的实现逻辑......
  • Jquery 将 JSON 列表的 某个属性值,添加到数组中,并判断一个值,在不在数据中
    jquery将JSON列表的某个属性值,添加到数组中如果你有一个JSON列表,并且想要将每个对象的某个属性值添加到数组中,你可以使用jQuery的$.each()函数来遍历JSON列表,并获取所需的属性值。以下是一个示例代码:varjsonList=[{"name":"John","age":30,"city":"NewYork"}......