react中hook封装一个table组件

目录

  • 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 ICommonTableProps<RecordType> extends TableProps<RecordType> {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 } = propsconst classes = useCommonTableStyles();if (!width) { return (<th {...restProps} />) };return (<Resizablewidth={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 Record<string, any> = any>(props: ICommonTableProps<RecordType>
) => {const { onCreate, onEdit, deleteBtn, isDrag = true } = props;const classes = useCommonTableStyles();const wrapperRef = useRef<HTMLDivElement>(null);const bodyRef = useRef(document.body);const size = useSize(bodyRef);const [scroll, setScroll] = useState<TableProps<any>['scroll']>({ x: 'max-content' });const [rescolumns, setResColumns] = useState<ColumnType<RecordType>[]>(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 重组为支持可拖拽的cellconst 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'dangeronClick={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] = useState<any>([]);const [currentPage, setCurrentPage] = useState<number>(1);const [currentSize, setCurrentSize] = useState<number>(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: TableRowSelection<any> = {onChange: (selectedRowKeys, selectedRows) => {setSelectedRow(selectedRowKeys);},};// 分页const handlePageChange = (page: number, size: number) => {setCurrentPage(page);setCurrentSize(size);// getList({ page, size, param: queryData }); // 获取table数据};const tableColumns: ColumnsType<any> = useMemo(() => {return [{title: '操作',dataIndex: 'code',fixed: 'left',width: '100px',render: (text, record) => (<divclassName={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 (<><CommonTablerowKey={'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}/><CommonTablerowKey={'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.hqwc.cn/news/458190.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

VMware虚拟机安装openEuler系统(一)(2024)

目录 一、下载ISO镜像 二、开始创建虚拟机 通过实践是学习openEuler开源Linux系统的最佳方式。因此我们首先得搭建一个openEuler实战环境&#xff0c;文章是在Windows系统上使用VMware Workstation虚拟化软件&#xff0c;安装和学习openEuler开源Linux操作系统。 使用虚拟机…

新型RedAlert勒索病毒针对VMWare ESXi服务器

前言 RedAlert勒索病毒又称为N13V勒索病毒&#xff0c;是一款2022年新型的勒索病毒&#xff0c;最早于2022年7月被首次曝光&#xff0c;主要针对Windows和Linux VMWare ESXi服务器进行加密攻击&#xff0c;到目前为止该勒索病毒黑客组织在其暗网网站上公布了一名受害者&#x…

人工智能专题:量子汇编语言和量子中间表示发展白皮书

今天分享的是人工智能系列深度研究报告&#xff1a;《人工智能专题&#xff1a;量子汇编语言和量子中间表示发展白皮书》。 &#xff08;报告出品方&#xff1a;量子信息网络产业联盟&#xff09; 报告共计&#xff1a;78页 量子计算与量子编程概述 随着社会生产力的发展&am…

vue3 之 商城项目—home

home—整体结构搭建 根据上面五个模块建目录图如下&#xff1a; home/index.vue <script setup> import HomeCategory from ./components/HomeCategory.vue import HomeBanner from ./components/HomeBanner.vue import HomeNew from ./components/HomeNew.vue import…

手势检测跟踪解决方案

美摄科技&#xff0c;作为业界领先的人工智能技术提供商&#xff0c;致力于为企业提供先进的手势检测与跟踪解决方案&#xff0c;以推动企业在智能化、高效化的道路上阔步前行。 一、手势检测与跟踪技术的优势 手势检测与跟踪技术作为人机交互的重要一环&#xff0c;具有以下…

Flask 入门7:使用 Flask-Moment 本地化日期和时间

如果Web应用的用户来自世界各地&#xff0c;那么处理日期和时间可不是一个简单的任务。服务器需要统一时间单位&#xff0c;这和用户所在的地理位置无关&#xff0c;所以一般使用协调世界时&#xff08;UTC&#xff09;。不过用户看到 UTC 格式的时间会感到困惑&#xff0c;他们…

雨云EPYC7702服务器上线了!适合幻兽帕鲁开服的VPS!雨云EPYC7702高防VPS性能测评

雨云游戏云上线了AMD EPYC 7702的VPS服务器&#xff0c;中等水平的单核性能&#xff0c;适合开幻兽帕鲁和我的世界1.17以下版本的服务器。 AMD Epyc 7702是一款64核心128线程&#xff0c;基础频率2.00 GHz加速频率高达3.35 GHz处理器&#xff0c;凭借着7 nm工艺及新一代Rome (…

SpringBoot:@Profile注解和Spring EL

&#x1f3e1;浩泽学编程&#xff1a;个人主页 &#x1f525; 推荐专栏&#xff1a;《深入浅出SpringBoot》《java对AI的调用开发》 《RabbitMQ》《Spring》《SpringMVC》 &#x1f6f8;学无止境&#xff0c;不骄不躁&#xff0c;知行合一 文章目录 前言一、Prof…

5年前端仔的2023年终总结

突然发现已经有好几个月没有写过博客总结过什么&#xff0c;小小辩解一下&#xff0c;其实并不是笔者停止的学习和总结&#xff0c;随着在前端这个行业的逐年深入&#xff0c;渐渐的很多收获不再是像之前简单的技术点的确定性描述讲解了&#xff0c;而是某个领域的知识体系的串…

数智文旅:智慧文旅中的数字化转型

在数字化浪潮席卷全球的今天&#xff0c;旅游业作为传统服务业的代表&#xff0c;正面临着前所未有的转型压力与机遇。智慧文旅&#xff0c;作为旅游业与数字技术深度融合的产物&#xff0c;不仅标志着旅游业进入了全新的发展阶段&#xff0c;更预示着未来旅游业将朝着更加智能…

ruoyi-nbcio中xxl-job的安装与使用

更多ruoyi-nbcio功能请看演示系统 gitee源代码地址 前后端代码&#xff1a; https://gitee.com/nbacheng/ruoyi-nbcio 演示地址&#xff1a; http://122.227.135.243:9666 更多nbcio-boot功能请看演示系统 gitee源代码地址 后端代码&#xff1a; https://gitee.com/nbach…

单片机接收PC发出的数据

#include<reg51.h> //包含单片机寄存器的头文件 /***************************************************** 函数功能&#xff1a;接收一个字节数据 ***************************************************/ unsigned char Receive(void) { unsigned char dat; …