Antd table组件的拖拽控制列宽

10,617 阅读2分钟

前言

其实antd的组件是支持这个拖拽列宽的功能的(非内部功能)。大家之所以没有在中文文档上发现,是因为,它在英文文档。

(这个官方示例,我用着差强人意,给大家推荐一个佬封装的hook:Antd 拖拽控制列宽

文档链接🔗:ant.design/components/…

根据文档的示例,大体使用方式是

  1. 使用table的components API修改表格头部为 react-resizable提供的组件
  2. 并在columns设置侦听函数,用于动态修改宽度 (onHeaderCell API)
  3. 还需要设置css,让控制组件显示在正确位置
  4. ProTable的使用也是一样的

react- resizable 官方文档🔗:github.com/react-grid-…

注意点:

  1. width一定要设置初始值,才能有控制组件
  2. css记得写上

官方示例

带了自己的一些代码解读

antd table 使用resizable

import { Table } from 'antd';
import type { ColumnsType, ColumnType } from 'antd/es/table';
import React, { useState } from 'react';
import type { ResizeCallbackData } from 'react-resizable';
import { Resizable } from 'react-resizable';

interface DataType {
  key: React.Key;
  date: string;
  amount: number;
  type: string;
  note: string;
}
// 定义头部组件
const ResizableTitle = (
  props: React.HTMLAttributes<any> & {
    onResize: (e: React.SyntheticEvent<Element>, data: ResizeCallbackData) => void;
    width: number;
  },
) => {
  const { onResize, width, ...restProps } = props;

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

  return (
    <Resizable
      width={width}
      height={0}
      handle={
        <span
          className="react-resizable-handle"
          onClick={e => {
            e.stopPropagation();
          }}
        />
      }
      onResize={onResize}
      draggableOpts={{ enableUserSelectHack: false }}
    >
      <th {...restProps} />
    </Resizable>
  );
};

const App: React.FC = () => {
  const [columns, setColumns] = useState<ColumnsType<DataType>>([
    {
      title: 'Date',
      dataIndex: 'date',
      width: 200,
    },
    {
      title: 'Amount',
      dataIndex: 'amount',
      width: 100,
      sorter: (a, b) => a.amount - b.amount,
    },
    {
      title: 'Type',
      dataIndex: 'type',
      width: 100,
    },
    {
      title: 'Note',
      dataIndex: 'note',
      width: 100,
    },
    {
      title: 'Action',
      key: 'action',
      render: () => <a>Delete</a>,
    },
  ]);
  const data: DataType[] = [
    {
      key: 0,
      date: '2018-02-11',
      amount: 120,
      type: 'income',
      note: 'transfer',
    },
    {
      key: 1,
      date: '2018-03-11',
      amount: 243,
      type: 'income',
      note: 'transfer',
    },
    {
      key: 2,
      date: '2018-04-11',
      amount: 98,
      type: 'income',
      note: 'transfer',
    },
  ];
  
  
  // 动态修改宽度
  const handleResize =
    (index: number) =>
    (_: React.SyntheticEvent<Element>, { size }: ResizeCallbackData) => {
      const newColumns = [...columns];
      newColumns[index] = {
        ...newColumns[index],
        width: size.width,
      };
      setColumns(newColumns);
    };
  // 设置侦听函数
  const mergeColumns: ColumnsType<DataType> = columns.map((col, index) => ({
    ...col,
    onHeaderCell: column => ({
      width: (column as ColumnType<DataType>).width,
      onResize: handleResize(index),
    }),
  }));

  return (
    <Table
      bordered
      // 消费头部组件
      components={{
        header: {
          cell: ResizableTitle,
        },
      }}
      columns={mergeColumns}
      dataSource={data}
    />
  );
};

export default App;

// 控制组件在正确位置
#components-table-demo-resizable-column .react-resizable { 
position: relative;
background-clip: padding-box;
} 
#components-table-demo-resizable-column .react-resizable-handle { 
position: absolute;
right: -5px;
bottom: 0;
z-index: 1;
width: 10px;
height: 100%;
cursor: col-resize;
}

总结

本次使用react-resizable + antd table,大致是这么一个流程:

  1. 首先react-resizable提供一个可以获取拖拽获取宽度的组件(一个返回 初始值+拖拽位移 的组件)
  2. 利用antd table提供的components API,将这个组件渲染在表头
  3. 利用css固定组件在右侧
  4. 最后利用onHeaderCell API修改宽度,实现拖拽控制列宽的效果

ps:所以什么时候antd table内置拖拽控制列宽功能?