antd Table 列宽可拖动

可作为单独组建


image.png
// index.tsx
import { Table } from "antd";
import type { ColumnType, TableProps } from "antd/es/table";
import { FC, useEffect, useMemo, useRef, useState } from "react";
import ResizeTitle from "./resizeTitle";

const Index: FC<TableProps<any>> = (props) => {
  const thsRef = useRef<Record<string, any>>({});

  const columns = useMemo(() => props.columns ?? [], [props.columns]);

  const [propsColumns, setPropsColumns] = useState<ColumnType<any>[]>([]);

  const scrollX = useMemo(
    () =>
      propsColumns
        .slice()
        .reduce((pre, next) => (pre += Number(next?.width ?? 200)), 0),
    [propsColumns]
  );

  const lastColumns = useMemo(() => {
    const initialColumns: ColumnType<any>[] = [];
    if (columns?.length === 0) {
      return [];
    }
    const handleResize = (dataIndex: any) => (width: number) => {
      if (!dataIndex) return;
      setPropsColumns((cur) =>
        cur.map((v) => ({
          ...v,
          width: v.dataIndex === dataIndex ? width : v.width,
        }))
      );
    };
    columns.forEach((n: any) => {
      if (propsColumns.find((v) => v.dataIndex === n.dataIndex)) {
        n.width = propsColumns.find((v) => v.dataIndex === n.dataIndex)?.width;
      }
      if (!n.fixed && n.dataIndex && n.title) {
        n.onHeaderCell = (wwcolumn: ColumnType<any>) => {
          return {
            width: wwcolumn.width,
            thRef: thsRef,
            dataIndex: JSON.stringify(n.dataIndex),
            onResize: handleResize(n.dataIndex),
          };
        };
      }
      initialColumns.push({ ...n, ellipsis: true });
    });
    return initialColumns;
  }, [columns, propsColumns]);

  useEffect(() => {
      setPropsColumns(columns)
  }, [columns])
  
  return (
    <>
      <Table
        {...props}
        components={{
          header: {
            cell: ResizeTitle,
          },
          ...props.components,
        }}
        scroll={{ x: scrollX, y: props.scroll?.y }}
        columns={lastColumns}
      />
    </>
  );
};

export default Index;

// resizeTitle.tsx
import { memo } from "react";
import Draggable from "react-draggable";
import styled from "styled-components";
import "react-resizable/css/styles.css";

const Handle = styled.div`
    position: absolute !important;
    right: 0 !important;
    bottom: 0 !important;
    z-index: 10 !important;
    width: 4px !important;
    height: 100% !important;
    background: none !important;
    cursor: col-resize !important;

    &:hover {
        background-color: #1890ff !important;
    }
`;

const ResizeableTitle = memo((props: any) => {
    const { onResize, width, thRef, dataIndex, ...restProps } = props;

    const tmplTH = <th {...restProps} />;

    if (!onResize) {
        return tmplTH;
    }

    const _width = width || thRef.current[dataIndex]?.clientWidth;

    return (
        <th ref={(e) => (thRef.current[dataIndex] = e)}>
        <div style={{ minWidth: 50 }} {...restProps}>
            {restProps.children}
        </div>
        <Draggable
            axis="x"
            position={{ x: 0, y: 0 }}
            onStop={(e, data) => {
                const lastWidth = _width + data.x > 50 ? _width + data.x : 50;
                onResize(lastWidth);
            }}
        >
            <Handle />
        </Draggable>
        </th>
    );
});

export default ResizeableTitle;

虚拟列表

import React, { FC, Key, useCallback, useMemo } from 'react';
import { TableProps } from "antd";
import { VList, scrollTo } from "virtuallist-antd";
import styled from 'styled-components';
import ProTable from "@/componets/ProTable";

interface ProScopeTableProps extends TableProps<any> {
    pageSize?: number
    current?: number
    loadDataSize?: number
    total?: number
    checkIds?: Key[]
    onLoadMore?: () => void
};

const ProScopeTable: FC<ProScopeTableProps> = (props) => {
    // 已加载多少条
    const loadSize = useMemo(() => props.dataSource?.map(item => item?.children)?.flat()?.length ?? 0, [props.dataSource])
    const scrollY = useMemo(() => props?.scroll?.y ?? 500, [props?.scroll?.y])
    const vc = useMemo(() => {
        return VList({
            height: scrollY,
            resetTopWhenDataChange: false
        })
    }, [scrollY])
    const handleScrollTop = useCallback(() => {
        scrollTo({ row: 0 })
    }, [])
    const handleScrollBottom = useCallback(() => {
        const row = props.dataSource?.map(item => item?.children)?.flat()?.length
        scrollTo({ row })
    }, [props.dataSource])

    return (
        <>
            <TableStyle
                height={scrollY}
                {...props}
                size={props.size || 'small'}
                pagination={false}
                scroll={{ y: scrollY }}
                components={vc}
            />
        </>
    )
}

export default ProScopeTable;

const TableStyle = styled(ProTable)<{height?: any}>`
    .virtuallist {
        min-height: ${props => props.height ?? '500px'} !important;
        tr {
            height: auto !important;
        }
    }
`
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容