【RaETable】🚀🚀🚀告别Form,RaETable表格列宽度支持拖动调整了,附带原理说明

raETable是react antd Easy Table 的缩写。旨在让开发者在react中使用 antd的Table时更 easy。

Github: github.com/mmdctjj/rae...

npm: www.npmjs.com/package/rae...

文档:mmdctjj.github.io/raetable

往期回顾

🚀 变更内容

最近工作的需求变动,antd表格的宽度需要支持拖动调整。

调研了一圈,呼声最高的方案是使用react-resizable库实现。

实现之后发现这个功能特别适合 RaETable 于是,我也给这个组件增加了这个功能。不过,不用担心,这个功能默认是关闭的,当你设置resize为 true 时才会开启该功能。

效果可以直接看这个示例

录制的工具限制,只有15帧动画,感兴趣的话可以到官网实际操作下。

mmdctjj.github.io/raetable/co...

🚀 实现原理

实现原理:

  • react-resizable提供了Resizable组件用于包括th元素,成为可以拖拽的元素。
  • 采用antd``Table组件提供的components属性,覆盖表头元素
  • 每次拖拽之后将最新的列宽度值设置为列的真实宽度值

github.com/react-compo...

js 复制代码
export interface TableComponents<RecordType> {
  table?: CustomizeComponent;
  header?: {
    wrapper?: CustomizeComponent;
    row?: CustomizeComponent;
    cell?: CustomizeComponent;
  };
  body?:
    | CustomizeScrollBody<RecordType>
    | {
        wrapper?: CustomizeComponent;
        row?: CustomizeComponent;
        cell?: CustomizeComponent;
      };
}

🚀 实现过程

💎 重写表头组件

js 复制代码
import { Resizable, ResizeCallbackData } from 'react-resizable';
import 'react-resizable/css/styles.css';

const ResizableTitle = (props: {
  [x: string]: any;
  onResize: ((e: React.SyntheticEvent, data: ResizeCallbackData) => any) | undefined;
  width: number;
}) => {
  const { onResize, width, ...restProps } = props;

  if (!width) {
    return <th {...restProps} />;
  }

  return (
    <Resizable width={width} height={0} onResize={onResize}>
      <th {...restProps} />
    </Resizable>
  );
};

💎 覆盖表头组件

js 复制代码
const ResizeTable = (
  props: JSX.IntrinsicAttributes &
    TableProps<any> & { children?: React.ReactNode } & {
      ref?: React.Ref<HTMLDivElement> | undefined;
    },
) => {
  const [columns, setColumns] = useState(props.columns ?? []);

  return (
    <Table
      {...props}
      columns={columns}
      components={{
        header: {
          cell: ResizableTitle,
        },
      }}
      scroll={{ x: 'max-content' }} // 添加滚动条以适应自适应宽度
    />
  );
};

💎 动态的更新表格列宽度

js 复制代码
  const handleResize =
    (index: number) =>
    (event: any, { size }: any) => {
      setColumns((prevColumns) => {
        const nextColumns = [...prevColumns];
        nextColumns[index] = {
          ...nextColumns[index],
          width: size.width,
        };
        return nextColumns;
      });
    };

  const resizableColumns = columns?.map((col: any, index: number) => ({
    ...col,
    onHeaderCell: (column: { width: number }) => ({
      width: column.width,
      onResize: handleResize(index),
    }),
  }));

完整代码如下

js 复制代码
import { Table, TableProps } from 'antd';
import React, { useState } from 'react';
import { Resizable, ResizeCallbackData } from 'react-resizable';
import 'react-resizable/css/styles.css';

const ResizableTitle = (props: {
  [x: string]: any;
  onResize: ((e: React.SyntheticEvent, data: ResizeCallbackData) => any) | undefined;
  width: number;
}) => {
  const { onResize, width, ...restProps } = props;

  if (!width) {
    return <th {...restProps} />;
  }

  return (
    <Resizable width={width} height={0} onResize={onResize}>
      <th {...restProps} />
    </Resizable>
  );
};

const ResizeTable = (
  props: JSX.IntrinsicAttributes &
    TableProps<any> & { children?: React.ReactNode } & {
      ref?: React.Ref<HTMLDivElement> | undefined;
    },
) => {
  const [columns, setColumns] = useState(props.columns ?? []);

  const handleResize =
    (index: number) =>
    (event: any, { size }: any) => {
      setColumns((prevColumns) => {
        const nextColumns = [...prevColumns];
        nextColumns[index] = {
          ...nextColumns[index],
          width: size.width,
        };
        return nextColumns;
      });
    };

  const resizableColumns = columns?.map((col: any, index: number) => ({
    ...col,
    onHeaderCell: (column: { width: number }) => ({
      width: column.width,
      onResize: handleResize(index),
    }),
  }));

  return (
    <Table
      {...props}
      columns={resizableColumns}
      components={{
        header: {
          cell: ResizableTitle,
        },
      }}
      scroll={{ x: 'max-content' }} // 添加滚动条以适应自适应宽度
    />
  );
};

export default ResizeTable;

🎉 最后

RaETable 是我独立开发的antd基于table组件的一揽子生态集合,常常用于B端业务处理,在敏捷开发场景事半功倍,效果显著,希望可以帮助更多的开发者。

如果你在使用中有任何的问题,都可以联系我。

好了,今天的分享就这些,文章中错误的地方欢迎指正。

相关推荐
总要学点什么12 分钟前
第104篇:三维特效-流动墙体效果——让贴图沿墙流动,它却只肯走一条对角线
开发语言·javascript·ecmascript·gis·webgl·材质·cesium
某哈压力大15 分钟前
SSH 突然 Connection reset?不是密钥坏了,是 OpenSSL 把 sshd 干趴了
前端·node.js·命令行
程序员大阳18 分钟前
副队长ES6+教程(3)--解构赋值
前端·javascript·es6·赋值·解构
神膘护体小月半36 分钟前
css - 元素背景图由 hover 触发,初次加载时闪动的解决办法
前端·javascript·css
程序员大阳1 小时前
副队长ES6+教程(2)--let 与 const
前端·javascript·es6·const·let·var
deli0071 小时前
写满 200GB 后 SSD 为什么掉到 95MB/s?SLC 缓存模型实测
前端
曦樂~2 小时前
【Web Development】03JavaScript 基础和事件
开发语言·前端·javascript
deli0072 小时前
HTTPS 的锁是怎么挂上的?TLS 1.3 握手 6 步实测
前端
程序员大阳2 小时前
副队长ES6+教程(1)--ES6+初识
前端·ecmascript·es6
码云社区3 小时前
智慧物业系统选型指南:房屋档案、账单管理与报修协作
前端·javascript·vue.js·智慧物业