由于项目多处使用到了table,所以这边我进行了封装,这边使用了react-resizable模块
1.第一步 安装模块
安装模块:npm install react-resizable -save
2.第二步 封装组件
handleResize.tsx 是用于改变列宽的width的值
/src/components/handleResize/handleResize.tsx
function handleResize(
col: { key?: any, width?: any },
size: { width: any },
oldColumn: any,
setColumn: Function,
) {
const newColumns = [...oldColumn];
newColumns.forEach((item) => {
if (item.key === col.key) {
item.width = size.width;
}
});
setColumn(newColumns);
}
export default handleResize;
ResuzeableTitle.tsx
src/components/ResizeableTitle/ResizeableTitle.tsx
import { Resizable } from 'react-resizable';
function ResizableTitle(props: {
[x: string]: any;
onResize: any;
className: any;
width?: number;
title: any;
children: any;
}) {
const {
onResize,
className,
width,
title,
children,
// eslint-disable-next-line @typescript-eslint/no-unused-vars
...restProps
} = props;
// const _ = require('lodash');
// ! 让antd的样式和resizable的样式共存
// const sty = _.merge(props, restProps);
return (
<Resizable width={width ?? 90} height={0} onResize={onResize}> //这边我设置了默认的列表宽度为90
<th>{children}</th>
{/* <th {...sty}>{children}</th> */}
</Resizable>
);
}
export default ResizableTitle;
StyledTable.tsx
/src/components/StyledTable/StyledTable.tsx
import React, { useMemo } from 'react';
import { Table } from 'antd';
import styled from 'styled-components';
import { TableProps } from 'antd/lib/table';
// import { PaginationConfig } from 'antd/lib/pagination';
import handleResize from '../handleResize/handleResize';
interface FTableProps<T> extends TableProps<T> {
editingKey?: string | number;
highlightRow?: object;
rowKey?: string | ((record: T, index?: number) => string);
onSaveRowEdit?: (record: T, data: object[]) => void;
onCancelRowEdit?: (record: T) => void;
onRowEditing?: (record: T) => void;
afterRowDrag?: (record: T) => void;
dragable?: boolean;
editRow?: boolean;
}
//由于我这边使用的表格和官网的表格样式有些不一致,所以这边用styled更改了原生的表格样式
const StyledTableWrapper = styled(Table)`
& .itsm-spin-nested-loading, & .itsm-spin-container {
height: 100% !important;
}
& .itsm-spin-container{
display: flex;
flex-direction: column;
}
& .itsm-table{
flex-grow: 1;
overflow: auto;
color: #fff;
background: none;
}
& .itsm-table-thead > tr > th,
.itsm-table-tbody > tr > td,
.itsm-table tfoot > tr > th,
.itsm-table tfoot > tr > td {
padding: 0 !important;
padding-left:14px !important;
}
& .itsm-table {
font-size: 14px !important;
line-height: 40px !important;
}
& .itsm-table-tbody > tr > td {
border-bottom: none !important;
}
& .itsm-table-thead > tr > th{
background: rgba(26, 78, 124, 0.2) !important;
color: #fff;
border-bottom: none !important;
}
& td.itsm-table-cell.itsm-table-cell-fix-right.itsm-table-cell-fix-right-first{
padding-left:0 !important;
}
& .itsm-table-cell-fix-left, .itsm-table-cell-fix-right{
background: none;
}
& .itsm-table-tbody > tr.itsm-table-row:hover > td, .itsm-table-tbody > tr > td.itsm-table-cell-row-hover{
background: #1d3058;
}
& .itsm-pagination-item-active{
background-color: #048CB6;
border-radius: 4px;
}
& .itsm-pagination-item a{
color:#fff;
}
& .itsm-pagination-options-quick-jumper input{
background-color: transparent;
border: 1px solid #048cb6;
border-radius: 4px;
color:#fff
}
& span.itsm-pagination-item-ellipsis{
color: #fff !important;
}
// & .anticon svg{
// color:#fff;
// }
& .itsm-select:not(.itsm-select-customize-input) .itsm-select-selector{
background-color: transparent;
border: 1px solid #048cb6;
border-radius: 4px;
}
& .itsm-select{
color:#fff;
}
& .itsm-table-empty .itsm-table-tbody > tr.itsm-table-placeholder, .itsm-empty-normal{
color:#fff;
}
& .itsm-table-tbody > tr.itsm-table-placeholder:hover > td{
background:transparent;
}
& .itsm-table-tbody > tr.itsm-table-row-selected > td{
background-color: transparent;
}
`;
interface StyledTableProps<T> extends FTableProps<T> {
hideEmptyColumns?: string[];
}
function StyledTable<T>({ columns, hideEmptyColumns, ...props }: StyledTableProps<T>) {
const pagination = useMemo(() => { //表格下面的页面
const mPagination = {
showTotal: (total: any, range: any[]) => `共有${total}条`,
size: 'small',
showSizeChanger: true,
showQuickJumper: true,
pageSizeOptions: [5, 10, 15, 20],
style: { marginRight: '20px', fontSize: '14px', marginTop: '20px', color: '#fff' },
};
if (props.pagination) {
return mPagination;
}
return mPagination;
}, [props.pagination]);
const customColumns = useMemo(() => {
if (!hideEmptyColumns || !hideEmptyColumns.length) {
return columns;
}
const dataList = props.dataSource;
if (!columns || !dataList) {
return columns;
}
const newColumns = [...columns];
newColumns.map((it) => ({
...it,
ellipsis: {
showTitle: true,
},
onHeaderCell: (col: { width?: any; key?: any; }) => ({
width: col.width,
// !传入newColumn,而不传入column是因为需要拿到有onHeaderCell的值,外面collumn的变化内部监听不到
onResize: (_e: any, { size }: any) => handleResize(col, size, newColumns, Function),
}),
}));
return newColumns;
}, [columns, hideEmptyColumns, props.dataSource]);
// @ts-ignore
return <StyledTableWrapper className="svgColor" bordered={props.bordered ?? false} pagination={pagination} {...props} columns={customColumns as any[]} />;
}
export default StyledTable;
3.第三步 使用Table表格
注意:如果表格在收缩列宽的时候,页面发生抖动的请求,请检查自己的key的值有没有填写,如果不想修改,请将handleResize.tsx里面的key修改成你所写的键名
注意:这边的columns不能写width值,因为会有冲突出现
/src/pages/Home/index.tsx
import ResizableTitle from '../../../components/ResizeableTitle/ResizeableTitle';
import handleResize from '../../../components/handleResize/handleResize';
import StyledTable from '../../../components/StyledTable/StyledTable';
import { useEffect, useMemo, useState } from 'react';
function Home() {
const columns = useMemo(() => {
const list: any = [
{
title: '单号',
dataIndex: 'No',
key: 'No',
},
{
title: '标题',
dataIndex: 'Title',
ellipsis: true,
key: 'Title',
},
{
title: '创建时间',
dataIndex: 'createTime',
key: 'createTime',
ellipsis: true,
},
];
return list;
}, []);
const [column, setColumn] = useState(columns);
useEffect(() => {
const newColumn = [...column].map((it) => ({
...it,
ellipsis: {
showTitle: true,
},
onHeaderCell: (col: { width?: any; key?: any; }) => ({
width: col.width,
// !传入newColumn,而不传入column是因为需要拿到有onHeaderCell的值,外面collumn的变化内部监听不到
onResize: (_e: any, { size }: any) => handleResize(col, size, newColumn, setColumn),
}),
}));
setColumn(newColumn);
}, [column]);
return (
<div>
<StyledTable
dataSource={[
{ No: '01', Title: '张三', createTime: '2022-01-01' },
{ No: '02', Title: '李四', createTime: '2022-01-01' },
{ No: '03', Title: '王二五', createTime: '2022-01-01' },
]}
rowKey="id"
style={{ flexGrow: 1, overflow: 'hidden' }}
rowClassName={(_record, index: number) => {
let className = '';
className = index % 2 === 0 ? 'oddRow' : 'evenRow';
return className;
}}
columns={column}
components={{
header: {
cell: ResizableTitle,
},
}}
/>
</div>
);
}
export default Home;