自定义滚动条,手撸等高虚拟列表

1,570 阅读3分钟

前言

在日常开发中对列表的展示都很熟悉,基本都是进行分页处理,有时会遇到需要一些不能使用分页方式来加载列表数据的情况,这就属于长列表渲染了,我们肯定是不能直接渲染这些数据,不然会导致交互卡顿,白屏。通常我们可以使用虚拟列表来优化。

什么是虚拟列表?就是只展示你想看见的部分,而不是展示全部的数据。实现原理就是滚动条每移动一段距离就计算当前滚动距离可视区域渲染的数据是什么。渲染10000条数据慢,渲染20条数据还能慢吗?虚拟列表又分为两种,一种是每一项元素等高,还有一种不等高。这篇文章先讲等高的情况

这是不等高的情况 自定义滚动条,手撸不等高虚拟列表 - 掘金 (juejin.cn)

正文

大体思路:通过对滑块移动获取到对应的transform值,根据滑块transform值计算列表滚动距离;然后将列表的滚动距离转化为列表transform值和计算在这个列表滚动距离时所在可视区域渲染的数据

先来看看效果,本文是会用transform来实现对自定义滚动条的滚动和内容的滚动

动画22.gif

滚动距离计算

由于是使用自定义滚动条实现的,所以我们必须要知道一些值之间的关系,比如滑块高度滑块最大可滚动距离滑块滚动距离内容实际高度可视区高度内容滚动距离

  • 滑块最大可滚动距离 = 可视区高度 - 滑块高度
  • 内容滚动距离 = 滑块滚动距离 * (内容实际高度 - 可视区高度) / 滑块最大可滚动距离

逐步分析

关键值计算

首先要知道几个关键值滑块高度滑块最大可滚动距离列表实际高度

code.png

滑块滚动距离计算

自定义滚动条的话就要监听几个事件,鼠标在滑块上按下鼠标放开鼠标的移动页面滚动页面大小变化,对于前几个事件的监听都可以理解,但是为什么要监听页面滚动页面大小变化呢?为了处理页面出现滚动条的情况

  • 滑块滚动距离 = 鼠标在可视区y的坐标 - 初始时滑块在页面中y轴坐标 - 鼠标在滑块中按下的y轴坐标;

有图就好理解多了 image.png

code.png

code.png

滚动条滚动计算

我们知道滑块滚动距离滑块高度与内容滚动距离的转化公式,很容易就可以得出内容滚动距离,但是实际的transform并不是内容滚动的距离。

  • 内容transform距离 = 内容实际滚动距离 - 当前列表开始渲染下标 * 列表每一项高度
  • 当前列表开始渲染下标 = Math.floor(内容实际滚动距离 / 列表每一项高度)

看图易懂 image.png

再加上边界的判断,完整代码就出来了

code.png

鼠标滑轮滚动计算

滚动条滚动计算明白了,那滑轮滚动计算就简简单单了。我们只需要知道当前内容的transform值,剩下的内容滚动距离滑块滚动距离都可以通过一步步的转化公式计算出来。

得出现在的transform值 code.png

  • 内容滚动距离 = 当前列表开始渲染下标 * 列表每一项高度 + 内容transform距离;
  • 滑块滚动距离 = 内容滚动距离 * 滑块最大可滚动距离 / (列表实际高度 - 可视区高度)

加上判断向上滚动还是向下滚动和边界的处理,完整代码就出来了

code.png

完整代码

仓库地址

结语

感兴趣的可以去试试