Antd+React+react-resizable实现表格拖拽功能

1、先看效果

Antd+React+react-resizable实现表格拖拽功能_第1张图片

2、环境准备

  "dependencies": {
    "antd": "^5.4.0",
    "react-resizable": "^3.0.4",

  },
  "devDependencies": {
    "@types/react": "^18.0.33",
    "@types/react-resizable": "^3.0.1",
  }

3、功能实现

一、先把拖拽组件写好

/**
 * 公共组件:实现拖拽
 */
import { isNumber } from 'lodash';
import { StyleHTMLAttributes } from 'react';
import { Resizable, ResizableProps } from 'react-resizable';

type ResizableTitleProps = ResizableProps & {
  resizable?: boolean;
  style: StyleHTMLAttributes;
};

const ResizableTitle = (props: ResizableTitleProps) => {
  const { onResize, width, resizable, ...restProps } = props;
  if (!width || !resizable) {
    return ;
  }
  let resizeWidth: any = width;
  if (!isNumber(resizeWidth)) {
    resizeWidth = Number(resizeWidth.replace('px', ''));
  }

  return (
     {
            e.stopPropagation();
          }}
        />
      }
      onResize={onResize}
      draggableOpts={{ enableUserSelectHack: true }}
      // maxConstraints={[800, 800]}
    >
      
    
  );
};

export default ResizableTitle;

 二、在antd写入tab,并引用拖拽组件

/**
 * 公共组件:静态表格
 */

import { Table } from 'antd';
import clsx from 'clsx';
import React, { useEffect, useState } from 'react';
import ResizableTitle from './ResizableTitle';
import styles from './index.less';

export interface ListTableProps {
  className?: any;
  rowClassName?: any;
  dimension?: number;
  columns?: any;
  dataSource?: any;
  pagination?: any;
  scroll?: object;
  virtual?: boolean;
  rowKey?: any;
  isShowScrollX?: boolean;
  vid?: string;
  isResizable?: boolean; //是否可退拽
  onChange?: (pagination: any, filters: any, sorter: any) => void;
}

// 暂无数据组件
const NoDataComponent = () => {
  return (
    
); }; const ListTable: React.FC = ({ className, rowClassName = () => '', onChange, dataSource, isShowScrollX, defaultFixedNode, columns: initCols, isResizable, vid = 'resize_table', ...props }) => { const [currentColumns, setCurrentColumns] = useState([]); const [leftRightNodeIsFixed, setLeftRightNodeIsFixe] = useState(defaultFixedNode); // 左右节点是否固定 useEffect(() => { setCurrentColumns(initCols); }, [initCols]); useEffect(() => { setCurrentColumns(initCols); }, [initCols]); // 计算宽度,当出现底部滚动条时,最左最右节点固定 const computedWidth = (columns: any) => { const widthAll = document.getElementsByClassName('ant-table-body')?.[0]?.clientWidth; const currentTabWidth = (columns || []).reduce((pre: number, cur: any) => { return Number(pre) + (Number(cur?.width) || 0); }, 0); setLeftRightNodeIsFixe(currentTabWidth > widthAll); }; // 拖拽后更新表格宽度 const handleResize = (index: number, colDataIndex?: string) => (e: any, { size }: { size: { width: number } }) => { if (!colDataIndex) { return; } setCurrentColumns((pre) => { let temp = [...pre]; temp[index] = { ...temp[index], width: size.width < 50 ? 50 : size.width, }; computedWidth(temp); return temp; }); }; const getColumns = (columns: any) => { return (columns || []).map((col: any, idx: number) => { return { ...col, onHeaderCell: (column: any) => ({ width: column.width || 100, resizable: isResizable && !column?.fixed, onResize: handleResize(idx, col.dataIndex as string), }), }; }); }; return ( { return rowClassName(record, index); }} locale={{ emptyText: }} {...(isResizable ? { components: { header: { cell: ResizableTitle, // 动态拖拽设置列宽 }, }, } : {})} columns={getColumns(currentColumns)} onChange={onChange} dataSource={dataSource} {...props} /> ); }; export default ListTable;

4、常见问题:

1、拖拽时,鼠标离开,拖拽被还原,80%原因是因为父组件触发了useState更新,column被还原成初始态,

2、拖拽要设置最小宽度和最大宽度,防止拖拽过程中找不到元素

你可能感兴趣的:(React,Antd,react.js,前端,javascript)