虚拟列表virtuallist-antd实现:

优点:
勾选、
展开子表格、
固定列、
固定头、
cell过长可折叠变成…
缺点:
会出现白屏、滑不动的情况

antd的虚拟表格

缺点:
不能勾选、展开
优点:
响应快,滑动起来十分丝滑
使用方法可参考这篇博客
关于新手指导IntroJS,vue项目(vue3)和react项目(ant-design)的引用

以下是虚拟列表virtuallist-antd的使用方法:

/*
 * @Descripttion: 复杂的虚拟表格组件 ComplexVirtualTable
 * 缺陷:width待优化 移动太快会白屏
 * @Author: Pandora
 * @Date: 2021-09-10 14:18:55
 */

import React, { useState, useMemo, useCallback, useEffect } from "react";
import ProTable from '@ant-design/pro-table';
import styles from '@/common.less'
import { VList } from "virtuallist-antd";
import { defaultConfig } from './config';
import { Resizable } from "react-resizable";

// size手动调整
const ResizableTitle = (props) => {
  const { onResize, width, ...restProps } = props;

  if (!width) {
    return <th {...restProps} />;
  }

  return (
    <Resizable
      width={width}
      height={0}
      handle={
        <span
          className="react-resizable-handle"
          onClick={(e) => {
            e.stopPropagation();
          }}
        />
      }
      onResize={onResize}
      draggableOpts={{ enableUserSelectHack: false }}
    >
      <th
        {...restProps}
        style={{ ...restProps?.style, borderRight: "1px solid #eee" }}
      />
    </Resizable>
  );
};

function ComplexVirtualTable(props) {
  // 主表格配置
  const initConfig = {
    ...defaultConfig,
    className: styles.virtual_list,
    pagination: {
      ...defaultConfig.pagination,
      total: props.total
    },
    ...props,
  };
  const [columns, setColumns] = useState(props.columns)
  const handleResize = useCallback((index) => {
    return (e, { size }) => {
      setColumns((pre) => {
        const temp = [...pre];
        temp[index] = {
          ...temp[index], 
          width: size.width
        };

        return temp;
      });
    };
  }, []);
  useEffect(() => {
    const cols = props.columns.map((col, index) => ({
      ...col,
      ellipsis: 'true',
      onHeaderCell: (column) => ({
        width: column.width,
        onResize: handleResize(index)
      })
    }));
    setColumns(cols)
  }, [props])
  
  const tableHeight = document.getElementsByClassName('ant-card')[0]?.clientHeight - 200 || 500
  // const tbody = document.getElementsByClassName('ant-table-body')[0]
  // tbody?.setAttribute('style', `max-height: ${tableHeight}`)
  console.log(tableHeight)
  const components = useMemo(() => {
    
    return {
      ...VList({
        height: tableHeight
      }),
      header: {
        cell: ResizableTitle
      }
    };
  }, []);
  return (
    <ProTable
      {...initConfig}
      columns={columns}
      scroll={{
        x: "100%",
				y: tableHeight // 滚动的高度, 可以是受控属性。 (number | string) be controlled.
			}}
      components={components}
        // VList({
          // height: 500, // 此值和scrollY值相同. 必传. (required).  same value for scrolly
          // onReachEnd: () => void, // (可选) 滚动条滚到底部触发api. (scrollbar to the end)
          // onScroll: () => void, // (可选) 滚动时触发的api. (triggered by scrolling)
          // vid: string, // (可选, 如果同一页面存在多个虚拟表格时必填.) 唯一标识. (unique vid, required when exist more vitual table on a page)
        // })}
    />
  );
}
export default ComplexVirtualTable

import ComplexVirtualTable from '@/components/Table/ComplexVirtualTable'
<ComplexVirtualTable
        columnsStateMap={columnsStateMap}
        onColumnsStateChange={(columnState) => {
          setColumnsStateMap(columnState)
        }}
        scroll={{
          y: '333px',
        }}
        {...config}
        rowSelection={{
          onChange: (_, selectedRows) => setSelectedRows(selectedRows),
          // fixed
        }}
        toolBarRender={() => [
            <div key="btns" className={styles.btns}>
              {getBtns()}
            </div>
          ]
        }
        columns={tableColumns}

        beforeSearchSubmit={
          (options) => {
            options.categoryId = options.secondCategoryName
            return options
          }
        }
        request={async (params) => {
          params.currentPage = params.current
          delete params.current
          setParams(params)
          // 表单搜索项会从 params 传入,传递给后端接口。
          const res = await querySysGoodsLibrary(params)
          config.total = res.data.total
          setConfig(JSON.parse(JSON.stringify(config)))
          return Promise.resolve({
            data: res.data.records,
            success: true,
          })
        }}

样式

// 虚拟表格子组件
.virtual_list{
  height: calc(100vh - 120px);
  
  :global(.ant-table-body) {
    border-bottom: 1px solid #f0f0f0;
  }
  :global(.ant-pro-field-index-column) {
    margin: auto;
  }
  :global(.ant-card-body) {
    height: calc(100vh - 130px);
  }
}
Logo

前往低代码交流专区

更多推荐