瀑布流+虚拟列表实践过程(react+ts版)

681 阅读4分钟

一、瀑布流

瀑布流布局的核心实现思想:

  1. 控制容器内每一列卡片的宽度相同(不同图片尺寸等比例缩放)
  2. 第一行卡片紧挨着排列,第二行开始采取贪心思想,每张卡片摆放到当前所有列中高度最小的一列下面

接下来是排布方式:

每个卡片相对容器的左上角顶点进行排布,采用 transform:translate3d(x,y,0) 可以开启GPU加速

最好由后端返回图片尺寸,如果未返回前端采用图片预加载计算图片尺寸

根据屏幕尺寸设置容器宽度以及列数,计算出列宽,并且支持在resize事件里自动切换

维护每列高度数组,数组长度即为列数,这个数组是为了确定下一行的卡片的定位


然后是计算卡片高度:

1、卡片内图片高度 computedImageHeight (非必须)

2、整个卡片高度 computedRealDomPos

二、虚拟列表

虚拟列表的思想:随着页面滚动,数据不断的加载变多,但是在容器里始终只渲染一定数量的dom元素(底下追加dom,上面移除dom),如果数据量庞大,页面也不会渲染卡顿。

1 不停的添加数据、移除数据,怎么保证滚动条不乱跳?

大的三层,视窗,容器,卡片。视窗里面套容器,容器里面是卡片,卡片相对容器定位,容器高度会持续增高,滚动条在视窗这一层

2 数据怎么管理?

分为原始数据rowCardList 和 渲染数据 cardList

渲染的数据有样式属性(h、y),记录下来,并更新到原始数据,根据滚动方向direction做不同的处理

direction:forward: 取数据计算样式及位置
direction:backward: 不再重新计算,直接从原始数据里面获取

3 请求数据的时机?

(相对容器底部设置一个sentinel dom,透明,判断enIndex已经取完一整页数据时,触发请求下一页)

4 添加、移除卡片的时机以及做哪些事情?

答:啥也不做,容器高度会越来越高,滚动条不会跳;(若是采用当前列高度减去卡片高度,容器高度减去卡片高度并且渲染的数据的y值都减去卡片高度,这种做法会让滚动条往上跳动,这里也回答了问题1)

添加卡片的时候,依次选择最短的列追加,最后取最高列的高度更新到容器高度 columnHeight

rowCardHeight 按行保存卡片信息(高度,坐标),为了记录每行最早露出的,以及最晚消失的

1⃣️ 添加的时候,direction === forward 渲染数据的时机?

第2行完全消失,移除这两行,并且尾部追加新的两行 (即就是第2行最长的那一行消失在可视区域)

2⃣️ 移除的时候,direction === backward 渲染数据的时机?(与forward是相反的过程)

倒数第二行完全消失,尾部移除两行,头部追加两行

(即就是倒数第2行y坐标最小的卡片,在一行中最早出现)

5 追加、移除多少条?

首先,追加和移除的条数是相等的,移除的时候,要保证卡片已经滚动到视窗外

要针对设备宽度,渲染不同的条数,暂时设置这些规格 :

35条-5*7行, [960, )

24条-4*6行, [690, 960)

18条-3*6行, [500, 690)

18条-2*9行 (, 500)

6 往回滚动之后,再继续往下滚动,怎么处理?

这时原始数据已经保留了位置、高度的卡片,可以直接渲染,不需要重复计算

卡片没有样式的执行 computedCardStyle 方法

7 滑动过快,来不及渲染,怎么处理?

lockScroll

确认渲染的 startIndex 和 endIndex时,加锁 lockScroll=true
渲染数据更新完成后,解锁 lockScroll = false

8 其它细节处理

防抖

触发resize时,动态计算 cardWidth 和 column,以及pageSize?

图片按照宽度等比压缩:?imageView2/2/w/210

图片预加载获取尺寸

图片懒加载 图片尺寸前端计算

七牛图片尺寸压缩