react中hook封装一个table组件 与 useColumns组件

目录

  • 1:react中hook封装一个table组件
    • 依赖
    • CommonTable / index.tsx
    • 使用组件
    • 效果
  • 2:useColumns组件
    • useColumns.tsx
    • 使用

1: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;

效果

在这里插入图片描述

2:useColumns组件

useColumns.tsx

import React, { useMemo, useCallback } from 'react';interface Args {handleEdit: (r: any) => void;handleSeeDetail: (r: any) => void;
}export const useColumns = ({ handleEdit, handleSeeDetail }: Args) => {const handleEvent = useCallback((v: string, record: any, e) => {e.stopPropagation();if (v === '编辑') {handleEdit(record);} else {handleSeeDetail(record);}},[handleSeeDetail, handleEdit],);// 渲染查看 || 编辑const showPop = useCallback((record: any) => {if (record.status === '1') {return (<spanonClick={(e) => handleEvent('编辑', record, e)}className="check-btn">编辑</span>);} else {return (<spanonClick={(e) => handleEvent('查看', record, e)}className="check-btn">查看</span>);}},[handleEvent],);const columnsData: any = useMemo(() => {const columns = [{title: '操作',width: '100px',fixed: 'left',render: (_: any, record: any) => showPop(record),},{title: '序号',width: '60px',render: (_: any, record: any, index: number) => `${index + 1}`,},{title: '名称',dataIndex: 'name',width: '130px',},{title: '年龄',dataIndex: 'age',},];return columns;}, [showPop]);return columnsData;
};export default useColumns;

使用

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';
import useColumns from "./useColumns"const useStyles = createUseStyles({table: {background: '#fff',padding: '16px',marginTop: '16px',width: '100%',},textBtn: {color: '#0068FF',cursor: 'pointer',userSelect: 'none',},
});
const TablePage = () => {const testData = [{ name: '测试1',age: 10 },{ name: '测试1',age: 20 },{ name: '测试1',age: 30 },]const handleSeeDetail = (row:any) => {console.log('查看', row);}const handleEdit = (row:any) => {console.log('编辑', row);}return (<><CommonTablerowKey={'id'}className={classes.table}dataSource={testData}scroll={{x: 'max-content',}}columns={useColumns({ handleSeeDetail, handleEdit })}/></>);
};
export default TablePage;

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/463095.html

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

相关文章

年假作业day2

1.打印字母图形 #include<stdio.h> #include<string.h> int main(int argc, const char *argv[]) { int i,j; char k; for(i1;i<7;i) { for(j1;j<i;j) { printf("%c",_); } for(j0,…

【小沐学GIS】基于Python绘制三维数字地球Earth(OpenGL)

&#x1f37a;三维数字地球系列相关文章如下&#x1f37a;&#xff1a;1【小沐学GIS】基于C绘制三维数字地球Earth&#xff08;OpenGL、glfw、glut&#xff09;第一期2【小沐学GIS】基于C绘制三维数字地球Earth&#xff08;OpenGL、glfw、glut&#xff09;第二期3【小沐学GIS】…

〖大前端 - ES6篇②〗- let和const

说明&#xff1a;该文属于 大前端全栈架构白宝书专栏&#xff0c;目前阶段免费&#xff0c;如需要项目实战或者是体系化资源&#xff0c;文末名片加V&#xff01;作者&#xff1a;哈哥撩编程&#xff0c;十余年工作经验, 从事过全栈研发、产品经理等工作&#xff0c;目前在公司…

跟着cherno手搓游戏引擎【22】CameraController、Resize

前置&#xff1a; YOTO.h: #pragma once//用于YOTO APP#include "YOTO/Application.h" #include"YOTO/Layer.h" #include "YOTO/Log.h"#include"YOTO/Core/Timestep.h"#include"YOTO/Input.h" #include"YOTO/KeyCod…

解析十六进制雷达数据格式:解析雷达FSPEC数据

以Cat62格式雷达数据为例&#xff0c;十六进制雷达数据部分代码&#xff1a; 3e0120bf7da4ffee0085 base_fspec_processor.h // // Created by qiaowei on 2024-02-03. //#ifndef RADARDATACONTROLLER_BASE_FSPEC_PROCESSOR_H #define RADARDATACONTROLLER_BASE_FSPEC_PROCESS…

深度学习的进展及其在各领域的应用

深度学习&#xff0c;作为人工智能的核心分支&#xff0c;近年来在全球范围内引起了广泛的关注和研究。它通过模拟人脑的学习机制&#xff0c;构建复杂的神经网络结构&#xff0c;从大量数据中学习并提取有用的特征表示&#xff0c;进而解决各种复杂的模式识别问题。 一、深度…

MFC实现遍历系统进程

今天我们来枚举系统中的进程和结束系统中进程。 认识几个API 1&#xff09;CreateToolhelp32Snapshot 用于创建系统快照 HANDLE WINAPI CreateToolhelp32Snapshot( __in DWORD dwFlags, //指定快照中包含的系统内容__in DWORD th32P…

前端JavaScript篇之call() 和 apply() 的区别?

目录 call() 和 apply() 的区别&#xff1f; call() 和 apply() 的区别&#xff1f; 在JavaScript中&#xff0c;call()和apply()都是用来改变函数中this指向的方法&#xff0c;它们的作用是一样的&#xff0c;只是传参的方式不同。 call()方法和apply()方法的第一个参数都是…

fyne x86 32位

条件&#xff1a; gcc 32位 任意go环境&#xff08;x86 x64均可&#xff09; fyne 编译&#xff1a; set goarch386 fyne package

算法---回溯(正文)

1.什么是回溯&#xff1f; 回溯算法的定义就是和暴力枚举一样枚举所有可能并加撤回&#xff0c;也能和暴力一样去掉一些重复&#xff08;在之前就被筛出&#xff0c;但还要枚举这个&#xff0c;我们可以跳过这个了---------这个就是回溯剪枝&#xff09;。但为什么回溯不是暴力…

【linux系统体验】-archlinux折腾日记

archlinux 一、系统安装二、系统配置及美化2.1 中文输入法2.2 安装virtualbox增强工具2.3 终端美化 三、问题总结3.1 一、系统安装 安装步骤人们已经总结了很多很全: Arch Linux图文安装教程 大体步骤&#xff1a; 磁盘分区安装 Linux内核配置系统&#xff08;基本软件&…

C#使用哈希表对XML文件进行查询

目录 一、使用的方法 1.Hashtable哈希表 2.Hashtable哈希表的Add方法 &#xff08;1&#xff09;定义 &#xff08;2&#xff09;示例 3.XML文件的使用 二、实例 1.源码 2.生成效果 可以通过使用哈希表可以对XML文件进行查询。 一、使用的方法 1.Hashtable哈希表…