ant-design/components/table/demo/virtual-list.md
二货机器人 72a7ba618f
New Table (#19678)
* chore: update rc-table

* add basic table style

* checked all logic

* checkbox support disabled

* selection style

* selection support radio

* add selections support

* selection extra style

* select all locale

* sorter logic

* add more desc

* init Filter hooks

* init filter hooks

* update style

* filter style

* filter style

* fix filter

* sort control

* ajax it

* add expandedable css

* expandable view style

* fixed style

* border style

* empty style

* fix pagination style

* add fixed demo

* un-comment

* clean up

* fix filter check logic

* fix overflow & ellipsis conflict

* fix tes

* adjust scroll shadow

* fix border fixed style

* add part of test case

* add filter test part

* more test case

* issue related test

* filter test

* adjust pagination logic

* fix pagination test case

* all selection test case

* table sorter test case

* table basic test

* fix test case

* update faq

* update expandable doc

* add v4 doc

* add summary docs

* more demo

* fix selection

* update snapshot

* update test case

* fix ff styling

* update rc-table

* update snapshot

* update snapshot

* fix lint

* fix style lint

* fix style

* update snapshot

* update desc

* fix missing icon
2019-11-15 14:35:25 +08:00

3.5 KiB

order title
30
en-US zh-CN
Virtual list 虚拟列表

zh-CN

通过 react-window 引入虚拟滚动方案,实现 100000 条数据的高性能表格。

en-US

Integrate virtual scroll with react-window to achieve a high performance table of 100,000 data.

import { VariableSizeGrid as Grid } from 'react-window';
import ResizeObserver from 'rc-resize-observer';
import classNames from 'classnames';
import { Table } from 'antd';

function VirtualTable(props) {
  const { columns, scroll, className } = props;
  const [tableWidth, setTableWidth] = React.useState(0);

  const widthColumnCount = columns.filter(({ width }) => !width).length;
  const mergedColumns = columns.map(column => {
    if (column.width) {
      return column;
    }

    return {
      ...column,
      width: Math.floor(tableWidth / widthColumnCount),
    };
  });

  const gridRef = React.useRef<any>();
  const [connectObject] = React.useState<any>(() => {
    const obj = {};
    Object.defineProperty(obj, 'scrollLeft', {
      get: () => null,
      set: (scrollLeft: number) => {
        if (gridRef.current) {
          gridRef.current.scrollTo({ scrollLeft });
        }
      },
    });

    return obj;
  });

  const resetVirtualGrid = () => {
    gridRef.current.resetAfterIndices({
      columnIndex: 0,
      shouldForceUpdate: false,
    });
  };

  React.useEffect(() => resetVirtualGrid, []);
  React.useEffect(() => resetVirtualGrid, [tableWidth]);

  const renderVirtualList = (rawData: object[], { scrollbarSize, ref, onScroll }: any) => {
    ref.current = connectObject;

    return (
      <Grid
        ref={gridRef}
        className="virtual-grid"
        columnCount={mergedColumns.length}
        columnWidth={index => {
          const { width } = mergedColumns[index];
          return index === mergedColumns.length - 1 ? width - scrollbarSize - 1 : width;
        }}
        height={scroll.y}
        rowCount={rawData.length}
        rowHeight={() => 54}
        width={tableWidth}
        onScroll={({ scrollLeft }) => {
          onScroll({ scrollLeft });
        }}
      >
        {({ columnIndex, rowIndex, style }) => (
          <div
            className={classNames('virtual-table-cell', {
              'virtual-table-cell-last': columnIndex === mergedColumns.length - 1,
            })}
            style={style}
          >
            {rawData[rowIndex][mergedColumns[columnIndex].dataIndex]}
          </div>
        )}
      </Grid>
    );
  };


  return (
    <ResizeObserver onResize={({ width }) => {
      setTableWidth(width);
    }}>
      <Table
        {...props}
        className={classNames(className, 'virtual-table')}
        columns={mergedColumns}
        pagination={false}
        components={{
          body: renderVirtualList,
        }}
      />
    </ResizeObserver>
  );
};

// Usage
const columns = [
  { title: 'A', dataIndex: 'key', width: 150 },
  { title: 'B', dataIndex: 'key'},
  { title: 'C', dataIndex: 'key'},
  { title: 'D', dataIndex: 'key'},
  { title: 'E', dataIndex: 'key', width: 200 },
  { title: 'F', dataIndex: 'key', width: 100 },
];

const data = [];

for (let i = 0; i < 100000; i += 1) {
  data.push({
    key: i,
  });
}

ReactDOM.render(
  <VirtualTable
    columns={columns}
    dataSource={data}
    scroll={{ y: 300, x: '100vw' }}
  />,
  mountNode,
);