虚拟滚动

335 阅读2分钟

场景描述

我们经常有这样的场景,例如一个可以浏览的数据列表,数据量已经超出一般的百十来条,另外还需要勾选进行操作进行批量化操作等。

常规数据量下,服务端侧性能保障是以分页形式给出接口的,视觉角度肯定是希望连贯加载没有分页的操作感,在这样的场景下,我们需要使用虚拟滚动,尽可能在任意时刻内只关注可视窗口区域的数据的流畅展示,而忽视被遮挡区域,同时又不能影响数据的正常渲染,访问到底进行判断后拉取下一页数据,纵享丝滑。



虚拟滚动原理

白话讲就是活在当下,不要去回首昨天,也不要去操心明天。

虚拟滚动核心思路就是每次只渲染可视区域的列表数,当滚动后动态的追加元素并通过顶部padding来撑起整个滚动内容

页面进行渲染的始终是固定的可视化区域的数据条数,而不是全部。

参考文章有很多很详细:

juejin.cn/post/684490…

额外值知识点:

display: 'none' 是渲染的。不是不展示就不会影响性能。

同样数据量下数据比对

举例子:1个简单table,数据量小是很能感受出来区别的,数据量越大区分越大,模拟10W条简单表格数据为例。

在业务场景下,都会比范例要复杂,所以渲染成本更大,所以体验感受的上限更低。

非虚拟滚动: 渲染时长5283ms,渲染全部数据。

虚拟滚动: 渲染时长137ms,渲染固定条数。

滚动加载组件封装

思路:

1.监听是否滚动到底

2.判断当前页是否为最后一页

3.非最后一页pageNumber + 1,最后一页提示已经到底。

1

import React, { FC, useState } from 'react';

interface IProps {

4

  maxBodyHeight?: number;

5

  pageNumberAdd?: (any: any) => void;

6

  pagination?: any;

7

}

8

9

const Index: FC = ({ maxBodyHeight, pageNumberAdd = () => {}, pagination, ...props }) => {

10

  // 是否还有数据

11

  const [isMore, setIsMore] = useState(true);

12

13

  return (

14

    <div

15

      style={{ overflowY: 'scroll' }}

16

      onScrollCapture={(e: any) => {

17

        if (e.target.localName === 'div' && e.target.className === 'next-table-body') {

18

          if (Math.round(e.target?.scrollTop) + e.target?.clientHeight === e.target?.scrollHeight) {

19

            if (Math.ceil(pagination.total / pagination.pageSize) === pagination.pageNumber) {

20

              setIsMore(false);

21

              return null;

22

            } else {

23

              pageNumberAdd(Number(pagination.pageNumber) + 1);

24

            }

25

          }

26

        }

27

      }}

28

    >

29

      <Table

30

31

        useVirtual

32

        maxBodyHeight={maxBodyHeight}

33

        fixedHeader

34

        {...props}

35

      />

36

      {!isMore ?

已经到底啦
: null}

37

   

38

  );

39

}

40

41

export default Index;

42

日常快速实现

1. fusion Table的虚拟滚动属性

结合fixedHeader和maxBodyHeight属性,可实现常规table指定高度的虚拟滚动。

2. fusion 虚拟滚动列表 VirtualList

使用与非列表的形式,例如大数量的标签,大数量的tag等。支持设置一屏数,缓冲区高度,以及跳转位置等。

组件给出了渲染思想:

zhuanlan.zhihu.com/p/55329238

3. antd Table

通过 react-window 引入虚拟滚动方案