长列表性能优化

需求场景

1.长列表,大约超过1000行数据

2.每一行至少8列,每一列都不是单纯的文本节点,都是input,select,checkbox之类的复杂组件,可以理解成可编辑表格。

3.列表可以进行拖拽排序

4.每行最后一列有删除按钮,可以进行删除行操作。

5.每一行有序号标识,序号不能去除,且必须显示出来。

6.锁列

问题

1.每次打开这个长列表,过多的数据,造成大量组件节点需要渲染,200行数据渲染大约需要12s

2.点击删除某一行的时候,行数越靠前,删除,需要重新渲染的节点越多,由于序号不能去掉要显示出来,假如删除第一行,后面2-200行都要重新渲染,就又是12s

优化

1.首先因为序号的原因,导致react本身对长列表key的性能优化失效。

2.需要拖拽排序,并且要显示滚动条,需要滚动加载无法使用。

3.考虑到IE兼容性,IntersectionObserver等一些新特性不能用

第一次优化方案

所以第一阶段考虑的性能优化,是虚拟滚动。virtualization虚拟化功能,是进行滚动加载无限长列表,大数据列表的一种常用性能优化技术,最常用的库,react-virtualized

虚拟化的基本思想

虚拟化就是说我们将需要渲染的内容限制在我们的给的固定容器中,给容器一个股东的高度与高度overflow:auto ,然后数据将在这个容器显示,我们只需要渲染视口容器中适合的数量节点,比如高度为500的容器,每一行50,那么我们一开始是不是渲染10行,就可以填充满视口容器。

对于这个方案,我们需要解决几个问题

1.如果只渲染10行,如何保证滚动条的显示与真实滚动条一致。

2.用户开始滚动后,数据如何显示

3.每一行的行高不是唯一确定的

滚动条问题

我们再开始渲染这个列表时,需要告诉虚拟化的这个组件,我们总的高度的,比如我们每一行是50,一共有1000行,那么高度就是50000。这样我们是可以直接到达真实滚动条显示效果的。

滚动问题

一旦用户开始滚动了,我们可以监听onScroll 事件来获取到滚动的垂直距离y坐标,根据y坐标,我们可以知道当前应该渲染到第几行。

但是如果用户快速滚动,为了不让有闪烁的效果,我们应该提前预先渲染好几行,来防止这种情况,比如我们需要展示10行,我们可以多渲染10行,作为储备,当用户开始滚动的时候,根据设置的阀值,再次提前渲染好额外待展示的行。

当然为了避免用户快速的滚动,导致频繁的渲染行,我们可以使用requestAnimationFrame来实现对渲染速率的控制,从而平滑的滚动

行高的问题

大致的想法是,我们应该在componentDidMount和componentDidUpdate等生命周期进行对高度信息的回调,也就是说我们在渲染每一行的时候,对外提供一行行高的回调,可以进行动态的指定行高,并且要实时的计算总的高度,以保证滚动条的正确显示。

但是这样并未完美解决,我们依赖有大量的渲染浪费。还需要一些优化

列表缓存

由于这里,我们一次显示渲染的数据并不多,我们可以利用react自身的优化,对每一行指定唯一的key,来提升节点的利用和优化。并且我们自身也可以对节点进行缓存,在滚动时遇到缓存中节点时,可直接使用。

列表回收

前面我们说了,要提前预渲染几个节点,以及可视区域的节点,然后滚动过程中,不断的创建新的可视区域节点,我们不做控制,那么最后也是所有的节点都被创建了,这样虽然将一次渲染1000,拆分为了多次,不会在首次打开的时候卡,但是如果这个时候,有数据操作导致列表需要重新渲染,依然会导致全列表的重新渲染,所以我们需要做列表的回收,永远只保证可视区域的节点与上下预渲染的节点数量即可,超出这个范围的节点进行回收缓存。

做到这里,我们基本解决我们的问题,首次打开,以及删除后,重新渲染的性能问题。

但是是不是这就是最优方案了呢,并不是,我们的需求当中还有两点要求,

1.拖拽排序

2.锁列

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值