虚拟列表优化长列表渲染及滚动

2,230 阅读1分钟

前端小白第一次遇到这种表格优化,把处理方法记录一下,和大家交流分享,共同学习。不妥之处请批评指正。

需求:

原表格数据量大、渲染慢、滚动卡顿;1000条30个数据列的表格会有明显卡顿; 不可抗力不能使用分页,另外有树形和排序的功能。

解决方法:

antd-table-virtual-list : antd-table 提供的虚拟列表方案无法同时实现「可展开/选择/拖拽」等功能;

virtuallist-antd: 可以快速地在原代码的基础上实现优化效果,改动较小,表格的扩展功能可以保留;(好像只支持函数组件的写法)

example:

  1. 需要优化的代码:(原代码包含了较多业务逻辑)
import 'Table' from 'antd';

<Table
  columns={columns} // 经过处理的
  dataSource={dataSource} // 已处理过的数据
  onExpand={this.onExpand} // 可展开的回调函数
  expandedRowKeys={expandedRowKeys}
  rowKey={(record: any) => record.id}
  scroll={{y: '55vh'}}
  pagination={false}
  loading={loading}
  onChange={this.handleTableChange} // 用于监听数据列排序的函数
/>
  1. 安装 virtuallist-antd

npm install --save virtuallist-antd

  1. 优化后:
// VisualTable.js
import React, { useMemo } from "react";
import { Table } from "antd";
import { VList } from "virtuallist-antd";

function VisualTable(props) {

  const vc1 = useMemo(() => {
    return VList({
      height: '55vh',
      vid: 'first',
      resetTopWhenDataChange: false // 当数据改变时是否回滚顶部
    })
  }, []);

  return (
    <>
      {/* 所有之前业务逻辑通过props传入,基本不用做修改,特殊情况特殊处理 */}
      <Table
        columns={props.columns}
        dataSource={props.dataSource}
        pagination={props.pagination}
        onExpand={props.onExpand}
        expandedRowKeys={props.expandedRowKeys}
        /** 不建议使用x: max-content. 如果columns有fixed, x为max-content的话. ellipsis会失效 */
        scroll={{ y: '55vh', x: "100%" }}
        loading={props.loading}
        rowKey={props.rowKey}
        components={vc1}
        onChange={props.onChange}
      />
    </>
  )
}

export default VisualTable;
- import 'Table' from 'antd';
+ import 'VisualTable' from 'VisualTable.tsx';

- <Table
+ <VisualTable
    columns={columns} // 经过处理的
    dataSource={dataSource} // 已处理过的数据
    onExpand={this.onExpand} // 可展开的回调函数
    expandedRowKeys={expandedRowKeys}
    rowKey={(record: any) => record.id}
    scroll={{y: '55vh'}}
    pagination={false}
    loading={loading}
    onChange={this.handleTableChange} // 用于监听数据列排序的函数
  />

问题:

原代码较为复杂(繁多且时间上不允许重构),点击展开后会修改dataSource,为了使点击展开后不回滚顶部,设置了resetTopWhenDataChange: false.

另外有一个很方便的api,根据需要,可回滚顶部。

import {scrollTo} from "virtuallist-antd";

// 需要的业务逻辑下使用,可回滚顶部;
scrollTo({row: 1, vid: '相应的vid'});