目录
- react中hook封装一个table组件
-
- 依赖
- CommonTable / index.tsx
- 使用组件
- 效果
react中hook封装一个table组件
依赖
cnpm i react-resizable --save
cnpm i ahooks
cnpm i --save-dev @types/react-resizable
CommonTable / index.tsx
import React, { useEffect, useMemo, useRef, useState, useCallback } from 'react';
import { createUseStyles } from 'react-jss';
import { Resizable } from 'react-resizable';
import { ColumnType } from 'antd/lib/table';
import { Table, Button } from 'antd';
import type { ButtonProps, TableProps } from 'antd';
import { useSize } from 'ahooks';
export interface ICommonTablePropsRecordType> extends TablePropsRecordType> {
onCreate?: () => void;
onEdit?: () => void;
deleteBtn?: {
props?: ButtonProps;
onDelete?: () => void;
};
isDrag?: boolean; // 控制table是否展示 可拖拽的表头
}
const useCommonTableStyles = createUseStyles({
wrapper: {
background: '#fff',
marginTop: '12px',
padding: '12px 12px'
},
header: {
display: 'flex',
marginTop: '8px',
marginBottom: '20px'
},
tablActions: {
display: 'flex',
flex: 1,
justifyContent: 'flex-end',
alignItems: 'center'
},
headerBtn: {
marginLeft: '16px'
},
resizableHandle : {
position: 'absolute',
right: '-5px',
bottom: 0,
zIndex: 1,
width: '10px',
height: '100%',
cursor: 'col-resize'
}
});
// 表头拖拽组件
const ResizableTitle = (props: any ) => {
const { onResize, width, ...restProps } = props
const classes = useCommonTableStyles();
if (!width) { return (th {...restProps} />) };
return (
Resizable
width={parseInt(width)}
height={0}
handle={
span className={classes.resizableHandle} onClick={e => { e.stopPropagation() }} />
}
onResize={onResize}
draggableOpts={{ enableUserSelectHack: false }}
>
th {...restProps} style={{ ...restProps?.style, userSelect: 'none' }} />
/Resizable>
);
};
export const CommonTable = RecordType extends Recordstring, any> = any>(
props: ICommonTablePropsRecordType>
) => {
const { onCreate, onEdit, deleteBtn, isDrag = true } = props;
const classes = useCommonTableStyles();
const wrapperRef = useRefHTMLDivElement>(null);
const bodyRef = useRef(document.body);
const size = useSize(bodyRef);
const [scroll, setScroll] = useStateTablePropsany>['scroll']>({ x: 'max-content' });
const [rescolumns, setResColumns] = useStateColumnTypeRecordType>[]>(props.columns || []);
const handleResize = (index: number): ((_: any, Resize: { size: { width: any } }) => void) => {
return (_: any, Resize: { size: { width: any; }; }) => {
const temp = [...rescolumns];
temp[index] = { ...temp[index], width: Resize.size.width };
setResColumns(temp);
};
};
// 把 columns 用 map 重组为支持可拖拽的cell
const columnsMap: any[] = useMemo(() => {
return (
rescolumns?.map((column:any,index:any) => ({
...column,
onHeaderCell: (col: { width: any; }) => ({ width: col.width, onResize: handleResize(index) }),
title: column.title,
})) || []
);
}, [rescolumns]);
useEffect(() => {
if (wrapperRef.current) {
const { top } = wrapperRef.current?.getBoundingClientRect();
setScroll({
x: 'max-content',
y: innerHeight - top - 210
});
}
}, [wrapperRef, size]);
return (
div className={classes.wrapper} ref={wrapperRef}>
div className={classes.header}>
div className={classes.tablActions}>
{onCreate && (
Button className={classes.headerBtn} type='primary' onClick={onCreate}>
新增
/Button>
)}
{onEdit && (
Button className={classes.headerBtn} type='default'>
编辑
/Button>
)}
{deleteBtn && (
Button
{...deleteBtn.props}
className={classes.headerBtn}
type='default'
danger
onClick={deleteBtn.onDelete}
>
删除
/Button>
)}
/div>
/div>
Table
scroll={scroll}
{...props}
components={isDrag ? { header: { cell: ResizableTitle } } : undefined}
columns={columnsMap}
/>
/div>
);
};
使用组件
import { createUseStyles } from 'react-jss';
import type { TableRowSelection } from 'antd/lib/table/interface';
import type { ColumnsType } from 'antd/lib/table';
import { useEffect, useMemo, useState, useRef } from 'react';
import { CommonTable } from '../components/CommonTable/index';
const useStyles = createUseStyles({
table: {
background: '#fff',
padding: '16px',
marginTop: '16px',
width: '100%',
},
textBtn: {
color: '#0068FF',
cursor: 'pointer',
userSelect: 'none',
},
});
const TablePage = () => {
const [tableData, setTableData] = useStateany>([]);
const [currentPage, setCurrentPage] = useStatenumber>(1);
const [currentSize, setCurrentSize] = useStatenumber>(20);
const classes = useStyles();
const [tableLoading, setTableLoading] = useState(false);
const [tableDataTotal, setTableDataTotal] = useState(0);
const [selectedRow, setSelectedRow] = useState([] as any); //控制表格是否已选
useEffect(() => {
const resTable = [
{ id: 1, type: 1, status: '草稿' },
{ id: 2, type: 0, status: '已完成' },
{ id: 3, type: 1, status: '草稿' },
];
setTableData(resTable);
}, []);
const rowSelection: TableRowSelectionany> = {
onChange: (selectedRowKeys, selectedRows) => {
setSelectedRow(selectedRowKeys);
},
};
// 分页
const handlePageChange = (page: number, size: number) => {
setCurrentPage(page);
setCurrentSize(size);
// getList({ page, size, param: queryData }); // 获取table数据
};
const tableColumns: ColumnsTypeany> = useMemo(() => {
return [
{
title: '操作',
dataIndex: 'code',
fixed: 'left',
width: '100px',
render: (text, record) => (
div
className={classes.textBtn}
onClick={() => {
console.log('onClick', text,"record",record);
}}
>
{record['status'] === '草稿' ? '编辑' : '查看'}
/div>
),
},
{
title: '序号',
dataIndex: 'id',
width: '60px',
render: (_, __, index) => index + 1 + (currentPage - 1) * currentSize,
},
{
title: '来源',
dataIndex: 'type',
// width: '130px', // 最后一个宽度不传
render: (_, __, index) => (_ === 1 ? '系统' : '手工'),
},
];服务器托管网
}, [classes.textBtn, currentPage, currentSize]);
return (
>
CommonTable
rowKey={'id'}
className={classes.table}
columns={tableColumns}
scroll={{
x: 'max-content',
}}
pagination={{
showTotal: () => `共 ${tableDataTotal} 条记录`,
onChange: (page, size) => handlePageChange(page, size),
hideOnSinglePage: false,
showQuickJumper: true,
showSizeChanger: true,
current: currentPage,
pageSize: currentSize,
total: tableDataTotal,
}}
dataSource={tableData}
loading={tableLoading}
rowSelection={rowSelection}
/>
CommonTable
rowKey={'id'}
isDrag={false}
className={classes.服务器托管网table}
columns={tableColumns}
scroll={{
x: 'max-content',
}}
pagination={{
showTotal: () => `共 ${tableDataTotal} 条记录`,
onChange: (page, size) => handlePageChange(page, size),
hideOnSinglePage: false,
showQuickJumper: true,
showSizeChanger: true,
current: currentPage,
pageSize: currentSize,
total: tableDataTotal,
}}
dataSource={tableData}
loading={tableLoading}
rowSelection={rowSelection}
/>
/>
);
};
export default TablePage;
效果
服务器托管,北京服务器托管,服务器租用 http://www.fwqtg.net
【开源中国 APP 全新上线】“动弹” 回归、集成大模型对话、畅读技术报告” 那些成功的数据库公司没有一家是通过性能比竞争对手更快而成功的。 作者:JORDAN TIGANI,DuckDB 公司 MotherDuck 联合创始人&CEO 本文和封面来源…