按需求我们需要把
antd
库中table
表格的表头,设置为可拖拽的,在antd
中并没有现成的属性方法,所以我们需要用到第三方库react-resizable
;
本文还封装了可拖拽表头的表格组件,其中有阻止冒泡防止拖拽时引起排序、选中文字等操作。
如果你急需此功能,那么可以直接滑倒底部拿取代码
。
yarn add antd react-resizable --save
代码如下:
import React, { useState } from 'react'
import { Table } from 'antd'
import { Resizable } from 'react-resizable'
import "react-resizable/css/styles.css" // 一定要引入样式,否则没有拖拽的小标
// 当然我们也可以不引入,使用自定义拖拽标标,请看下面详情
需要放在组件外部,否则每次拖拽无法更新!
// 可伸缩表头组件,放到组件外
const ResizableTitle = ({ onResize, width, ...restProps }) => {
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} style={{ ...restProps?.style, userSelect: 'none' }} />
</Resizable>
);
};
// 表格数据
const dataSource = [
{ _id: 1, label: '范德萨1', gender: '男' },
{ _id: 2, label: '范德萨2', gender: '女' },
{ _id: 3, label: '范德萨3', gender: '男' },
{ _id: 4, label: '范德萨4', gender: '男' },
{ _id: 5, label: '范德萨5', gender: '女' },
]
// 表格列
const columns = [
{
title: '#',
dataIndex: '_id',
width: 60,
ellipsis: true,
},
{
title: '名称',
dataIndex: 'label',
width: 200,
ellipsis: true,
},
{
title: '性别',
dataIndex: 'gender',
width: 200,
ellipsis: true,
},
{
title: '操作',
key: 'action',
// width: 200,
ellipsis: true,
render: () => (
<a>修改</a>
),
},
];
表格列的最后一列
不要设置宽度
,否则会引起拉伸就会触发以下异常
!。
// 可伸缩表头组件
const [column, setColumn] = useState(
columns.map(it => {
it.ellipsis = {
showTitle: true
}
it.onHeaderCell = col => ({
width: col.width,
// !传入newColumn,而不传入column是因为需要拿到有onHeaderCell的值,外面collumn的变化内部监听不到
onResize: (e, { size }) => handleResize(col, size),
})
return it;
}
)
);
// table的th实时宽度拖拽的改变
const handleResize = (col, size) => {
setColumn(column.map(item => {
// 如果这个判断对不上,列宽可以移动但是会引起错乱
if (item.dataIndex === col.dataIndex) {
item.width = size.width;
}
return item
}))
}
在css或less中设置对应的类名样式,也可以设置为自定义的拖拽图标
// 取消引入样式,通过设置类名,来设置拖拽的标志
.react-resizable-handle {
position: absolute;
right: -5px;
bottom: 0;
z-index: 1;
width: 10px;
height: 100%;
cursor: col-resize;
}
// table的th实时宽度拖拽的改变
<Table
rowKey={'_id'}
columns={column}
dataSource={dataSource}
components={{
header: {
cell: ResizableTitle,
},
}}
></Table>
直接拿代码
components/ResizableTableModel/index.jsx
// components/ResizableTableModel/index.jsx
// 可拖拽表格组件
import { useState } from 'react';
import { Table } from 'antd';
import { Resizable } from 'react-resizable';
import './index.css';
// 表头拖拽组件
const ResizableTitle = ({ onResize, width, ...restProps }) => {
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} style={{ ...restProps?.style, userSelect: 'none' }} />
</Resizable>
);
};
// 带拖拽表格组件
const ResizableTable = ({ columns = [], ...props }) => {
// * 列数据
const [cols, setCols] = useState(columns);
const colsArray = cols.map((col, index) => {
return {
...col,
onHeaderCell: column => ({ width: column.width, onResize: handleResize(index) })
};
});
// todo 调整列宽
const handleResize = index => {
return (_, { size }) => {
const temp = [...cols];
temp[index] = { ...temp[index], width: size.width };
setCols(temp);
};
};
return (
<Table
components={{ header: { cell: ResizableTitle } }}
columns={colsArray}
{...props}
/>
);
};
export default ResizableTable;
components/ResizableTableModel/index.css
// components/ResizableTableModel/index.css
.react-resizable-handle {
position: absolute;
right: -5px;
bottom: 0;
z-index: 1;
width: 10px;
height: 100%;
cursor: col-resize;
}
pages/home/index.jsx
// pages/home/index.jsx
import React from 'react'
import { Divider, Table } from 'antd'
import ResizeableTableModel from '@/components/ResizeableTableModel'
const dataSource = [
{ _id: 1, label: '范德萨1', gender: '男' },
{ _id: 2, label: '范德萨2', gender: '女' },
{ _id: 3, label: '范德萨3', gender: '男' },
{ _id: 4, label: '范德萨4', gender: '男' },
{ _id: 5, label: '范德萨5', gender: '女' },
]
const columns = [
{
title: '#',
dataIndex: '_id',
width: 60,
ellipsis: true,
},
{
title: '名称',
dataIndex: 'label',
width: 200,
ellipsis: true,
},
{
title: '性别',
dataIndex: 'gender',
width: 200,
ellipsis: true,
},
{
title: '操作',
key: 'action',
width: 200,
ellipsis: true,
render: () => (
<a>修改</a>
),
},
];
const Layout = () => {
return (
<>
<Divider children="组件表格" />
<ResizeableTableModel
rowKey={'_id'}
columns={columns}
dataSource={dataSource}
/>
</>
)
}
export default Layout
要注意以下两点:
制作不易,看完给小编点个赞吧!