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

news/2024/7/15 18:10:22 标签: react.js, 前端, javascript

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<any>;
};

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

  return (
    <Resizable
      width={resizeWidth}
      height={0}
      handle={
        <span
          className="react-resizable-handle"
          onClick={(e) => {
            e.stopPropagation();
          }}
        />
      }
      onResize={onResize}
      draggableOpts={{ enableUserSelectHack: true }}
      // maxConstraints={[800, 800]}
    >
      <th
        {...restProps}
        style={{
          ...restProps?.style,
          width: `${resizeWidth}px`,
          borderRight: '1px solid rgba(2, 9, 23, 70%)',
        }}
      />
    </Resizable>
  );
};

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 (
    <div className={clsx(['h-[250px]', 'flex justify-center items-center'])}>
      <div
        className={clsx([
          'w-[76px] h-[94px]',
          'bg-[url("/images/no-data.svg")] bg-no-repeat',
        ])}
      />
    </div>
  );
};

const ListTable: React.FC<ListTableProps> = ({
  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 (
    <Table
      rowClassName={(record, index) => {
        return rowClassName(record, index);
      }}
      locale={{ emptyText: <NoDataComponent /> }}
      {...(isResizable
        ? {
            components: {
              header: {
                cell: ResizableTitle, // 动态拖拽设置列宽
              },
            },
          }
        : {})}
      columns={getColumns(currentColumns)}
      onChange={onChange}
      dataSource={dataSource}
      {...props}
    />
  );
};

export default ListTable;

4、常见问题:

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

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


http://www.niftyadmin.cn/n/5365938.html

相关文章

golang开源定时任务调度框架

golang开源定时任务调度框架 Go语言中有很多开源的定时任务调度框架&#xff0c;以下几个是比较流行常用的&#xff1a; golang开源定时任务框架介绍 cron 一个基于Cron表达式的定时任务库&#xff0c;可以精确到秒级。它提供了简单易用的API来定义和管理定时任务&#xff…

如何在Ubuntu系统部署SVN服务并在无公网ip环境访问内网svn资料库

文章目录 前言1. Ubuntu安装SVN服务2. 修改配置文件2.1 修改svnserve.conf文件2.2 修改passwd文件2.3 修改authz文件 3. 启动svn服务4. 内网穿透4.1 安装cpolar内网穿透4.2 创建隧道映射本地端口 5. 测试公网访问6. 配置固定公网TCP端口地址6.1 保留一个固定的公网TCP端口地址6…

Git的一些基本操作

初始git 我们给出下面的一个场景&#xff0c;在大学里&#xff0c;一些老师在我们做完实验之后喜欢让我们交实验报告&#xff0c;假设我们有一个比较追求完美的老师和一个勤奋的学生&#xff0c;这个学生叫做小帅&#xff0c;那天小帅桑勤奋的完成实验报告&#xff0c;在第二天…

【项目技术点总结之三】使用Java生成复杂好看的word或pdf报告的解决方案

前言 项目中往往会遇到需要生成报告的场景&#xff0c;不管是简单报告还是复杂报告&#xff0c;其实都需要找很多资料去尝试&#xff0c;本文会提出几种个人完美解决报告生成的解决方案&#xff0c;而且会提出几个失败但是能生成报告的设想&#xff0c;当然都是踩过坑的&#…

代码随想录算法训练营day 25|第七章 回溯算法part03

39. 组合总和 本题是集合里元素可以用无数次&#xff0c;那么和组合问题的差别 其实仅在于 startIndex上的控制 题目链接/文章讲解&#xff1a;代码随想录 视频讲解&#xff1a;带你学透回溯算法-组合总和&#xff08;对应「leetcode」力扣题目&#xff1a;39.组合总和&#x…

实践:从库分页参数

最近在写用户账单的功能&#xff0c;需要查询到两年千的消费记录&#xff0c;但是目前消费记录日志表里面记录的是一年内的数据&#xff0c;对于一年前的记录都记录在了归档表。因此想要查询两年前的数据就必须要查询归档表。 对于正常的情况&#xff0c;先查主表&#xff0c;当…

JVM 性能调优 - JVM 参数基础(2)

查看 JDK 版本 $ java -version java version "1.8.0_151" Java(TM) SE Runtime Environment (build 1.8.0_151-b12) Java HotSpot(TM) 64-Bit Server VM (build 25.151-b12, mixed mode) 查看 Java 帮助文档 $ java -help 用法: java [-options] class [args...] …

【证书管理】实验报告

证书管理实验 【实验环境】 ISES客户端 【实验步骤】 查看证书 查看证书详细信息 选择任意证书状态&#xff0c;在下方“证书列表”中出现符合要求的所有证书。在“证书列表”中点击要查看证书&#xff0c;在右侧“证书详细信息”栏出现被选证书信息。 上述操作如图1.2.…