可作为单独组建
// index.tsx
import { Table } from "antd";
import type { ColumnType, TableProps } from "antd/es/table";
import { FC, useEffect, useMemo, useRef, useState } from "react";
import ResizeTitle from "./resizeTitle";
const Index: FC<TableProps<any>> = (props) => {
const thsRef = useRef<Record<string, any>>({});
const columns = useMemo(() => props.columns ?? [], [props.columns]);
const [propsColumns, setPropsColumns] = useState<ColumnType<any>[]>([]);
const scrollX = useMemo(
() =>
propsColumns
.slice()
.reduce((pre, next) => (pre += Number(next?.width ?? 200)), 0),
[propsColumns]
);
const lastColumns = useMemo(() => {
const initialColumns: ColumnType<any>[] = [];
if (columns?.length === 0) {
return [];
}
const handleResize = (dataIndex: any) => (width: number) => {
if (!dataIndex) return;
setPropsColumns((cur) =>
cur.map((v) => ({
...v,
width: v.dataIndex === dataIndex ? width : v.width,
}))
);
};
columns.forEach((n: any) => {
if (propsColumns.find((v) => v.dataIndex === n.dataIndex)) {
n.width = propsColumns.find((v) => v.dataIndex === n.dataIndex)?.width;
}
if (!n.fixed && n.dataIndex && n.title) {
n.onHeaderCell = (wwcolumn: ColumnType<any>) => {
return {
width: wwcolumn.width,
thRef: thsRef,
dataIndex: JSON.stringify(n.dataIndex),
onResize: handleResize(n.dataIndex),
};
};
}
initialColumns.push({ ...n, ellipsis: true });
});
return initialColumns;
}, [columns, propsColumns]);
useEffect(() => {
setPropsColumns(columns)
}, [columns])
return (
<>
<Table
{...props}
components={{
header: {
cell: ResizeTitle,
},
}}
scroll={{ x: scrollX, y: props.scroll?.y }}
columns={lastColumns}
/>
</>
);
};
export default Index;
// resizeTitle.tsx
import { memo } from "react";
import Draggable from "react-draggable";
import styled from "styled-components";
import "react-resizable/css/styles.css";
const Handle = styled.div`
position: absolute !important;
right: 0 !important;
bottom: 0 !important;
z-index: 10 !important;
width: 4px !important;
height: 100% !important;
background: none !important;
cursor: col-resize !important;
&:hover {
background-color: #1890ff !important;
}
`;
const ResizeableTitle = memo((props: any) => {
const { onResize, width, thRef, dataIndex, ...restProps } = props;
const tmplTH = <th {...restProps} />;
if (!onResize) {
return tmplTH;
}
const _width = width || thRef.current[dataIndex]?.clientWidth;
return (
<th ref={(e) => (thRef.current[dataIndex] = e)}>
<div style={{ minWidth: 50 }} {...restProps}>
{restProps.children}
</div>
<Draggable
axis="x"
position={{ x: 0, y: 0 }}
onStop={(e, data) => {
const lastWidth = _width + data.x > 50 ? _width + data.x : 50;
onResize(lastWidth);
}}
>
<Handle />
</Draggable>
</th>
);
});
export default ResizeableTitle;