【Ant Design Table + React】表格列伸缩实现

news2024/11/15 15:52:03

需求背景:需要实现Antd Table 组件的列伸缩,宽度可以拖拽

在Antd 3.x 的版本中是保留的列伸缩的Demo例子的:
在这里插入图片描述
借助 react-resizable 可以实现伸缩列。

# npm 安装
npm install react-resizable --save

# yarn 安装
yarn add react-resizable

参考官方的Demo,封装一个ResizableTable组件:

import { Table } from 'antd';
import type { ColumnsType } from 'antd/lib/table';
import { useEffect,useState } from 'react';
import { Resizable } from 'react-resizable';
import styles from './resizableTable.less';

/**
 * 处理松开鼠标还会拖动的问题
 * 参考思路:在点击拖动时,使用浏览器API Selection.removeAllRanges 清空原本误选的文本。
 */
const clearSelection = () => {
  if (window.getSelection) {
    const selection = window.getSelection();
    if (selection) {
      if (selection.empty) {
        // Chrome
        selection.empty();
      } else if (selection.removeAllRanges) {
        // Firefox
        selection.removeAllRanges();
      }
    }
  } 
   else if (document.selection && document.selection.empty) {
     // IE
     document.selection.empty();
   }
};

export const ResizableTitle = (props: any) => {
  const { onResize, width, minWidth, maxWidth, ...restProps } = props;

  // 没有原始宽度的列,不支持伸缩;会出现从自适应宽度一下子跳到拖动位置;也可以自行增加参数,如 disableResize
  if (!width) {
    return <th {...restProps} />;
  }

  const minConstraints: [number, number] | undefined = minWidth
    ? [minWidth, -Infinity]
    : undefined;
  const maxConstraints: [number, number] | undefined = maxWidth
    ? [maxWidth, +Infinity]
    : undefined;
  return (
    <Resizable
      width={width}
      height={0} // 不需要调整高度,设为 0
      minConstraints={minConstraints}
      maxConstraints={maxConstraints}
      handle={
        <span
          className="react-resizable-handle"
          onClick={(e) => {
            // 阻止冒泡
            e.stopPropagation();
          }}
        />
      }
      onResize={onResize}
      draggableOpts={{
        enableUserSelectHack: false,
        onMouseDown: () => {
          // 处理在 Windows Chrome 和 Edge 松开鼠标依然能拖动
          clearSelection();
        },
      }}
    >
      <th {...restProps} />
    </Resizable>
  );
};

interface DataType {
  name: {
    first: string;
    last: string;
  };
  gender: string;
  email: string;
  login: {
    uuid: string;
  };
}
const columnsData: ColumnsType<DataType> = [
  {
    title: 'Name',
    dataIndex: 'name',
    sorter: true,
    render: (name) => `${name.first} ${name.last}`,
    width: '20%',
  },
  {
    title: 'Gender',
    dataIndex: 'gender',
    filters: [
      { text: 'Male', value: 'male' },
      { text: 'Female', value: 'female' },
    ],
    width: '20%',
  },
  {
    title: 'Email',
    dataIndex: 'email',
  },
];

const ResizableTable = () => {
  const curColumns: ColumnsType<DataType> = columnsData; // 可以是通过props 传进来的,这里用常量做例子
  const [column, setColumns] = useState<ColumnsType<any>>([]);
  // 拖动时更新表格列
  const handleResize = (index: number) => {
    return (_e: any, { size }: any) => {
      const newCols = [...column];
      newCols[index] = {
        ...newCols[index],
        width: size.width || '100%',
      };
      setColumns(newCols);
    };
  };

  const mergeColumns = column.map((col, index) => ({
    ...col,
    onHeaderCell: (column: any) => ({
      width: column.width ?? 100,
      // 每一列增加 minWidth, maxWidth 作为 ResizableTitle 的 props
      minWidth: 50,
      // maxWidth: 1000,
      onResize: handleResize(index),
    }),
  }));

  useEffect(() => {
    console.log('变化', curColumns);
    if (curColumns) {
      setColumns(curColumns);
    }
  }, [curColumns]);

  return (
    <div className={styles.resizeTable}>
      <Table
        size="small"
        components={{
          header: {
            cell: ResizableTitle,
          },
        }}
        columns={mergeColumns}
        dataSource={[]}
      />
    </div>
  );
};
export default ResizableTable;


必须引入样式 resizableTable.less

.resizeTable {
  :global {
    .react-resizable {
      position: relative;
      background-clip: padding-box;
    }

    .react-resizable-handle {
      position: absolute;
      width: 10px;
      height: 100%;
      bottom: 0;
      right: -5px;
      cursor: col-resize;
      background-image: none;
      z-index: 1;
    }

    .ant-table-filter-column,
    .ant-table-column-sorters {
      display: flex;

      /* co1umn 从上到下 */
      align-items: center;

      /* center代表水平方向 */
      justify-content: space-around;
      min-width: 70px;
    }

    .ant-table-thead>tr>th .ant-table-column-sorter {
      // margin-top: -21px;
      display: table-cell;
      vertical-align: middle;
    }
  }
}

必须保持一列宽度不设置,自适应。否则效果不对。

但我用这个插件后还是不太 OK,总有一些bug,比如如果拖动了不设置宽的列,整个伸缩就会变形;而且如果列数很多的情况下,自适应列效果不理想。

所有这个方案能用但不是很好用。
可以参考:https://juejin.cn/post/7182423243553734717


后续解决方案:

在查阅资料时,看到有个大佬封装好了一个伸缩hook use-antd-resizable-header,使用起来方便简单。遂引入项目。
https://github.com/hemengke1997/use-antd-resizable-header

pnpm add @minko-fe/use-antd-resizable-header

在这里插入图片描述
引入封装组件示例:

import { Table } from 'antd';
import { useAntdResizableHeader } from '@minko-fe/use-antd-resizable-header';
import '@minko-fe/use-antd-resizable-header/dist/style.css';

/** 自定义函数 */
import { isLocaleEn } from '@/utils/commont_rely';

/** type 类申明 */
import type { IProps } from '..'; // 自己封装的表格propsType, 仅作参考

/** 自定义样式 */
import './style.less';

/** ===================================
 * @name: 可伸缩列的表格组件
 * 注意:至少一列不能拖动(width 不设置即可),请保持至少一列的宽自适应
 *======================================*/

interface ResizableTableProps extends IProps {
  // 特殊配置
  defaultWidth?: number; // 设置不能拖动列的最小宽度 默认 120
  minConstraints?: number; // 拖动最小宽度 默认 60
  maxConstraints?: number; // 拖动最大宽度 默认800 可设置无穷
}

export default function ResizableTable(props: ResizableTableProps) {
  const { title, defaultWidth, minConstraints, maxConstraints } = props;
  const columns = props?.columns || []; // 组件传过来的colums
  const { components, resizableColumns, tableWidth } = useAntdResizableHeader({
    columns,
    defaultWidth: defaultWidth || 120,
    minConstraints: minConstraints || 60,
    maxConstraints: maxConstraints || 800,
  });

  return (
    <div className="resizableTable">
      <Table
        title={title}
        size="small"
        dataSource={data} // 组件传过来的data
        columns={resizableColumns}
        components={components}
        scroll={{ x: tableWidth }}
      />
    </div>
  );
}

使用方便,效果理想,推荐使用这个插件。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1114026.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

字符函数和字符串函数(详解大全)

重点 C语言中对字符和字符串的处理很是频繁&#xff0c;但是C语言本身是没有字符串类型的&#xff0c;字符串通常放在 常量字符串 中或者 字符数组 中。 字符串常量 适用于那些对它不做修改的字符串函数. 1.函数介绍 1.1strlen size_t strlen ( const char * str ); ⭐字符…

Linux——centos7.4磁盘空间调整分配

安装centos7.4操作系统时&#xff0c;采用默认安装方式&#xff0c;导致磁盘分配不太合理&#xff0c;于是重新进行磁盘空间分配。 1、cnetos7.4默认安装完成时磁盘分配情况 可以看到/dev/mapper/centos-home分区占用大部分空间&#xff0c;如今想将根目录空间增大。 注意&…

pandas写入MySQL

安装好pandas、mysql pip install pandas pip install pymysql 导入pandas、mysql import pymysql as mysql import pandas as pd 建立连接 conmysql.connect(host10.10.0.221,userroot,passwordroot,databasepandas,port3306,charsetutf8) 创建游标 curcon.cursor() 读…

R语言处理数量很大(千万级及以上)的数据时的拆分策略-案例一

主要是用R中的groupb_by和 summarise分组查询和统计数据量

碰到it运维故障怎么办丫?突发IT事故怎么快速解决?

随着信息技术的快速发展&#xff0c;企业对于IT系统的依赖程度越来越高。但IT系统突发事件的风险也在不断增加&#xff0c;例如突发故障&#xff0c;例如数据泄露、例如数据入侵等等。那碰到这种it运维故障怎么办&#xff1f;突发IT事故怎么快速解决&#xff1f; 碰到it运维故障…

广度优先搜索(Breadth First Search, BFS)算法

广度优先搜索(Breadth First Search, BFS) 广度优先搜索是一种盲目搜索算法&#xff0c;它认为所有状态(或者说结点)都是等价的&#xff0c;不存在优劣之分。 假如我们把所有需要搜索的状态组成一棵树来看&#xff0c;广搜就是一层搜完再搜下一层&#xff0c;直到找出目标结点…

旅游业媒体套餐7个诀窍助你轻松实现销售目标-华媒舍

旅游业是一个竞争激烈的行业&#xff0c;成功营销对于吸引客户和实现销售目标至关重要。借助媒体资源是一种有效的方式。本文将介绍7个诀窍&#xff0c;借助旅游业媒体套餐轻松实现销售目标。 1. 策划细致的新闻稿 新闻稿是介绍旅游产品和服务的重要工具。确保新闻稿中包含吸引…

【精选】2023网络安全学习路线 非常详细 推荐学习

关键词&#xff1a;网络安全入门、渗透测试学习、零基础学安全、网络安全学习路线 分享2套零基础、进阶学习网络安全/渗透测试教程 第一套是Web安全学习笔记 该笔记详细介绍了计算机网络协议、信息收集、常见漏洞、内网渗透、御用技术等等&#xff0c;全文全面成体系&#x…

京东店铺所有商品数据接口及店铺商品数据分析

获取京东店铺所有商品数据的接口是京东开放平台提供的接口&#xff0c;通过该接口可以获取店铺所有商品数据。 通过京东开放平台接口获取店铺所有商品数据的方法如下&#xff1a; 在开放平台注册成为开发者并创建一个应用&#xff0c;获取到所需的 App Key 和 App Secret 等信…

PHP 基础/练习

练习 成绩定级 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>成绩定级脚本</title> </…

Windows 事件日志监控

Windows 事件日志是记录 Microsoft 系统上发生的所有活动的文件&#xff0c;在 Windows 环境中&#xff0c;将记录系统上托管的系统、安全性和应用程序的事件&#xff0c;事件日志提供包含有关事件的详细信息&#xff0c;包括日期、时间、事件 ID、源、事件类型和发起它的用户。…

spring cloud Eureka集群模式搭建(IDEA中运行)

spring cloud Eureka集群模式搭建&#xff08;IDEA中运行&#xff09; 新建springboot 工程工程整体目录配置文件IDEA中部署以jar包形式启动总结 新建springboot 工程 新建一个springboot 工程&#xff0c;命名为&#xff1a;eureka_server。 其中pom.xml文件为&#xff1a; …

el-input无法输入的问题和表单验证失败问题(亲测有效)-开发bug总结4

大部分无法输入的问题&#xff1a;基本都是没有进行v-model双向数据绑定&#xff0c;这个很好解决。 本人项目中遇到的bug问题如下&#xff1a; 点击添加&#xff0c;表单内可输入用户名 和 用户姓名&#xff0c;但有时会偶发出现无法这两个input框里面无法输入内容。 原因&a…

使用 Rust 开发:以太坊与 Layer2 生态建设新趋势

Rust 是一种系统编程语言&#xff0c;以其出色的性能、内存安全和并发性而闻名&#xff0c;在区块链和 Web3 中广泛应用&#xff0c;大多数编程语言和开发框架都以 Rust 为核心&#xff0c;如 Polkadot、Solana、NEAR、Elrond&#xff08;现名 MultiversX&#xff09;、Hyperle…

探索房产小程序源码中的十大必备功能

作为房地产行业的专家&#xff0c;我们深知房产小程序在实现高效交易和提升用户体验方面的重要性。选择适合的房产小程序源码&#xff0c;关乎着您的平台能否脱颖而出。在本文中&#xff0c;我将为您揭示房产小程序中不可或缺的十大必备功能&#xff0c;助您确保您的小程序具备…

CSDN 使用体验:一路向上

使用CSDN已经很多年了&#xff0c;这些年我真的在这一平台上收获了很多&#xff0c;而这些年CSDN自身也在不断进步&#xff0c;一步步成长&#xff0c;尤其是在最近的使用过程中&#xff0c;我感受到了CSDN前所未有的包容性、全面性&#xff0c;并且收获成就感。 包容性 随着…

Linux 下 Java 安装字体方法

因上线访问图字体乱码了&#xff0c;因为在windows下设置的微软雅黑&#xff0c;linux默认是没有的&#xff0c;所以需要给jdk安装一个微软雅黑字体。按照步骤来&#xff0c;so easy&#xff01; 1&#xff09;首先找到windows下面的字体&#xff0c;不用去其他地方下了&#…

干货:电视机顶盒哪个牌子好?双11必看网络机顶盒排行榜

电视机顶盒是我们必不可少的&#xff0c;新手们在面对众多品牌和产品是难免疑惑电视机顶盒哪个牌子好&#xff0c;双十一买哪款电视机顶盒最实惠&#xff1f;我将给大家分享的是业内公认的网络机顶盒排行榜&#xff0c;想知道哪些电视盒子品牌最值得买&#xff0c;看这篇就足够…

【vue】使用less报错:显示this.getOptions is not a function

在vue-cli中使用 lang“less” 时报错&#xff1a; Module build failed: TypeError: this.getOptions is not a function at Object.lessLoader 原因&#xff1a;版本过高所致&#xff0c;所用版本为 解决&#xff1a;降低版本&#xff1a;npm install less-loader4.1.0 --s…

c: Queue Calling in Ubuntu

/*** file TakeNumber.h* author your name (geovindu)* brief * version 0.1* date 2023-10-20* * copyright Copyright (c) 2023 站在巨人的肩膀上 Standing on the Shoulders of Giants* */#ifndef TAKENUMBER_H #define TAKENUMBER_H#include <stdio.h> #include <…