当前位置: 首页 > news >正文

基于AntDesign二次封装table组件

二次封装table组件

我基于AntDesign当中的table完成了table的二次封装,它主要有以下几个功能:

  • 展示数据

  • 提供批量删除的方法进行批量删除

  • 提供删除按钮,进行删除操作

  • 提供导出单个为excel表格的接口,进行excel导出操作

  • 在这里插入图片描述

  • 提供编辑按钮,进行编辑操作
    在这里插入图片描述

  • 提供添加按钮,进行添加操作
    在这里插入图片描述

大致的步骤:

1、类型定义部分

(1)表格配置类型:
// 1、定义表格配置类型
interface TableConfig<T> {url: string;columns: TableProps<T>["columns"];requestParams?: Record<string, any>;// 添加行选择相关属性rowSelection?: boolean;rowKey?: string;// 自定义查询参数queryParams?: Record<string, any>;scroll?: {x: number;y: number;};//   批量删除配置batchDeleteConfig?: {enableBatchDelete: boolean;batchUrl: string;confirmMessage?: string;};deleteConfig?: {//删除的配置enableDelete: boolean;// 删除单个singleUrl: string;// 确认消息confirmMessage?: string;// 主键字段名,默认'id'keyField: string;};//   导出为excel配置exportExcel?: {//删除的配置enableExcel: boolean;// 确认消息confirmMessage?: string;// 主键字段名,默认'id'keyField: string;header: string[];};// 点击编辑的配置editConfig?: {enableEdit: boolean;editUrl: string;keyField: string;confirmMessage?: string;columns: any;};
//   添加的配置addConfig?: {enableAdd: boolean;addUrl: string;confirmMessage?: string;columns: any;};
}

他主要是由基本配置、批量删除配置、删除配置、导出为excel配置、编辑配置以及添加配置组成

基本配置:

获取数据的url、columns、rowSelection(可以进行选择)、rowKey、queryParams(请求参数)、scroll

url: string; // 请求数据的URLcolumns: TableProps<T>["columns"]; // 表格列配置requestParams?: Record<string, any>; // 请求参数rowSelection?: boolean; // 是否启用行选择rowKey?: string; // 行唯一标识queryParams?: Record<string, any>; // 自定义查询参数scroll?: { // 滚动配置x: number;y: number;};

其他的增删改查配置都差不多,大概的结构:

   enable: boolean;Url: string;confirmMessage?: string;

如果是需要关键词查找的要加上:

 keyField: string;

导出为excel的要提供header数组:

 exportExcel?: {//删除的配置enableExcel: boolean;// 确认消息confirmMessage?: string;// 主键字段名,默认'id'keyField: string;header: string[];};

编辑的要提供columns:在点击编辑的时候会弹出一个弹窗,弹窗的内容是按照这里面的内容进行渲染的,具体渲染规则我在后面会写到

columns: any;

添加也是如此

(2)表格组件属性类型

规范表格组件的属性结构,进行了表格属性类型的配置,主要包括表格配置项、可选的行点击事件处理函数以及选择变更事件处理函数

interface EnhancedTableProps<T> {tableConfig: TableConfig<T>;onRowClick?: (record: T) => void;onSelectChange?: (selectedRowKeys: React.Key[], selectedRows: T[]) => void;
}
(3)组件引用类型

对于提供出去的方法,比如 handelBatchDelete、handelAdd进行声明

interface EnhancedTableRef {handelBatchDelete?: () => void;handelAdd?: () => void;
}

2、状态管理部分

const [dataSource, setDataSource] = useState<any[]>([]); // 表格数据源
const [loading, setLoading] = useState<boolean>(false); // 加载状态
const [page, setPage] = useState<number>(1); // 当前页码
const [pageSize, setPageSize] = useState<number>(10); // 每页条数
const [total, setTotal] = useState<number>(0); // 数据总量
const [isModelOpen, setIsModelOpen] = useState(false); // 模态框显示状态
const [title, setTitle] = useState(""); // 模态框标题
const [currentRecord, setCurrentRecord] = useState<any>({}); // 当前操作的记录
const [operationType, setOperationType] = useState<'add' | 'edit'>('add'); // 操作类型
const [selectedRowKeys, setSelectedRowKeys] = useState<React.Key[]>([]); // 选中的行 keys
const [selectedRows, setSelectedRows] = useState<[]>([]); // 选中的行数据

3、核心功能实现

(1)数据加载

逻辑:根据配置项中的url、请求参数以及page、pageSize进行请求

    const loadData = async () => {setLoading(true);const { data } = await getList(tableConfig.url, {...tableConfig.queryParams,page,pageSize,});setDataSource(data.data.list);setTotal(data.data.total);setLoading(false);};

这里面有一个公共的请求数据函数:

export const getList = async (url : string , data : SearchType) => {const fullUrl = new URL(url, API_BASE_URL).href;return  post(fullUrl, data );
};

(2)分页处理

 const pagiNationChange = (page: number, pageSize: number) => {setPage(page);setPageSize(pageSize);};

(3)行选择配置

主要目的:

  • 实现了表格行选择功能的封装,支持单选或多选
  • 维护了组件内部的选择状态( selectedRowKeys 和 selectedRows )
  • 提供了与父组件的通信机制,让父组件能够响应选择状态的变化
 // 定义行选择配置const rowSelection = tableConfig.rowSelection? {selectedRowKeys,//绑定当前选中行的键数组(来自组件状态)onChange: (keys: React.Key[], rows: any[]) => {setSelectedRowKeys(keys);setSelectedRows(rows as []);const { onSelectChange } = restProps as EnhancedTableProps<any>;onSelectChange?.(keys, rows);},}: undefined;

选择变化函数(onChange):接收选中行的键数组、选中行的数据数组然后更新组件内部状态,最后通知父组件

通知父组件主要是通过restProps中的onSelectChange,进行设置

4、扩展功能的实现

(1)删除功能

逻辑:获取关键词进行请求

  const handelDeleteItem = async (id: string) => {if (!tableConfig.deleteConfig?.enableDelete) {return;}const keyField = tableConfig.deleteConfig.keyField || "id";//获取关键词setLoading(true);try {await deleteItem(tableConfig.deleteConfig.singleUrl, keyField, id);loadData();message.success("删除成功");} catch (error) {message.error("删除失败");} finally {setLoading(false);}};

删除也是写了一个公共的删除函数的

export const deleteItem = async (url : string , keyField : string , data : any) => {const fullUrl = new URL(url, API_BASE_URL).href;return post(fullUrl, {[keyField] : data});
}

这里注意一下 {[keyField] : data}使用键值对的方式

(2)编辑&&添加功能

逻辑:都是打开弹窗->填写弹窗的内容

弹窗也在后面进行说明

编辑:打开弹窗->设置弹窗标题->将当前要编辑的记录存入状态,供弹窗内部使用->设置当前操作类型为 “edit”(编辑),用于区分新增、编辑等不同操作

 const handelEdit = (record?: any) => {if (!tableConfig.editConfig?.enableEdit) {return;}setIsModelOpen(true);setTitle(tableConfig.editConfig?.confirmMessage || "编辑");setCurrentRecord(record);setOperationType('edit');};

添加:同上

    const handelAdd = () => {if (!tableConfig.addConfig?.enableAdd) {return;}setIsModelOpen(true);setTitle(tableConfig.addConfig?.confirmMessage || "添加");setCurrentRecord({});setOperationType('add');};
(3)批量删除

逻辑:传入url和 selectedRowKeys进行批量删除

  //   批量删除的方法:const handelBatchDelete = async () => {if (!tableConfig.batchDeleteConfig?.enableBatchDelete) {return;}setLoading(true);try {await deleteItems(tableConfig.batchDeleteConfig.batchUrl,selectedRowKeys);loadData();message.success("删除成功");} catch (error) {message.error("删除失败");} finally {setLoading(false);}};

5、组件通信

通过 useImperativeHandle 暴露方法给父组件:

React.useImperativeHandle(ref, () => ({handelBatchDelete,handelAdd,
}));

6、生命周期与副作用函数

加载数据

// 初始加载数据
useEffect(() => {loadData();
}, [page, pageSize, tableConfig.queryParams]);

动态配置操作项

 operateColumn.render = (value, record) => {return (<>{tableConfig.deleteConfig?.enableDelete && (<RenderOperateButtonstype="primary"size="small"dangerclassName="ml mr mb"confirmMessage={tableConfig.deleteConfig?.confirmMessage}option={() => {const keyField =tableConfig.deleteConfig?.keyField || "id";handleDeleteItem((record as any)[keyField]);}}/>)}{tableConfig.exportExcel?.enableExcel && (<RenderOperateButtonstype="primary"size="small"className="ml mr"confirmMessage={tableConfig.exportExcel?.confirmMessage}option={() => {const header = tableConfig.exportExcel?.header || [];exportToExcel([record], header);}}/>)}{tableConfig.editConfig && (<RenderOperateButtonstype="primary"size="small"className="ml mr"confirmMessage={tableConfig.editConfig?.confirmMessage}option={() => {handleEdit(record);}}/>)}</>);};

进行动态渲染是根据每一个配置项的enable进行条件渲染的,react好像不太支持if(之前准备直接使用if,但是被警告了),所以改为了现在这种方式:

  {tableConfig.editConfig && (<Button</Button>)}

首先寻找到操作列

tableConfig.columns.find((col) => col.key === "operate") :查找 key 为 "operate" 的列(即操作列)

然后进行自定义渲染,关于封装的RenderOperateButtons也留在后面进行讲解

7、UI部分

主要是弹窗、表格以及分页器

表格和分页器

  <Tableloading={loading}rowKey={tableConfig.rowKey || "id"}rowSelection={rowSelection}columns={tableConfig.columns}dataSource={dataSource}scroll={tableConfig.scroll}pagination={false}/><PaginationclassName="mm mt"total={total}showSizeChangercurrent={page}pageSize={pageSize}onChange={pagiNationChange}/>

8、其他封装的组件

(1)弹窗

InputTable:主要用于创建和编辑数据时展示表单界面。

主要逻辑:通过配置化方式生成表单,支持多种表单控件类型(输入框、单选框、下拉选择器等),并提供表单验证。

接口定义:

主要是由列配置和组件属性接口两部分组成

列配置:

interface ColumnConfig {name: string; // 字段名label: string; // 标签名type: 'input' | 'radio' | 'select' | 'textarea'; // 字段类型required?: boolean; // 是否必填rules?: any[]; // 验证规则options?: { value: string; label: string }[]; // 选择类型的选项placeholder?: string; // 占位符span?: number; // 占用列数initialValue?: any; // 初始值
}

组件属性:

interface FormProps {visible: boolean;//是否显示hideMode: () => void;//隐藏弹窗title: string;//标题loadData: () => void;//加载数据的函数initialData: any;//初始数据columns: ColumnConfig[]; // 列配置onFinish: (values: any) => void; // 可选的提交回调
}

状态管理

组件使用 Ant Design 的 Form.useForm 钩子创建表单实例,用于管理表单状态和操作:

 const { visible, hideMode, title, loadData, columns, initialData, onFinish } = props;const [form] = Form.useForm<any>();

生命周期和副作用

使用 useEffect 钩子处理组件的副作用,主要负责在模态框显示时初始化表单数据:

useEffect(() => {if (visible) {if (title.includes("添加")) {form.resetFields();} else if (initialData) {form.setFieldsValue(initialData);}}
}, [visible, title, initialData]);

因为涉及到多种情况要使用这个弹窗,为了解决添加没有数据,编辑的时候实现数据的回显所以使用这样比较死的方法。

处理列分组:根据传入的colmns进行渲染

      // 根据列类型渲染不同的表单控件const renderFormItem = () => {switch (column.type) {case 'input':return <Input placeholder={column.placeholder || ``} />;case 'radio':return (<Radio.Groupoptions={column.options || []}/>);case 'select':return (<Selectplaceholder={column.placeholder || ``}options={column.options || []}/>);case 'textarea':return <Input.TextArea placeholder={column.placeholder || ``} />;default:return <Input placeholder={column.placeholder || ``} />;}};currentRow.push(<Col key={`col-${index}-${column.name}`} span={span}><Form.Itemlabel={column.label}name={column.name}rules={column.rules || (column.required ? [{ required: true, message: `请输入${column.label}` }] : [])}className="[&_.ant-form-item-label]>label:text-gray-600">{renderFormItem()}</Form.Item></Col>);currentSpan += span;});

表单提交函数:

  const handleFinish = async (values: any) => {try {// 如果提供了自定义提交回调,则使用它if (onFinish) {onFinish(values);} else {// 否则使用默认的提交逻辑const { data } = await changeUserList(values);message.success(data.message);loadData();}hideMode();} catch (error) {message.error("提交失败");}};

UI 渲染
组件的 UI 结构主要包含一个 Ant Design 的 Modal 组件,内部嵌套 Form 组件:

 <div className="inputTable"><Modalcenteredtitle={title}onCancel={hideMode}open={visible}width={50 + "vw"}footer={[<Button key="cancel" onClick={hideMode}>取消</Button>,<Button key="submit" type="primary" onClick={() => form.submit()}>确认提交</Button>,]}><Formform={form}name="dynamicForm"labelCol={{ span: 8 }}wrapperCol={{ span: 16 }}validateTrigger="onSubmit"onFinish={handleFinish}autoComplete="off">{renderColumnsInRows()}// 渲染表单列</Form></Modal></div>
(2)按钮
import { Button } from "antd"
interface ButtonConfig {type?: "link" | "text" | "default" | "primary" | "dashed" | undefined;size?: "small" | "middle" | "large";className?: string;option?:() => void;confirmMessage?:string;danger?:boolean;}export default function RenderOperateButtons(config:ButtonConfig) {return (<Buttontype={config.type}size={config.size}className={config.className}onClick={config.option}danger={config.danger || false}>{config.confirmMessage}</Button>)}

9、使用说明

EnhancedTable 是基于 Ant Design Table 组件封装的增强表格组件,提供了数据加载、分页、行选择、删除、编辑、添加等一体化功能,支持配置化使用,减少重复代码编写。

(1)组件属性
属性名类型说明必填
tableConfigTableConfig表格配置对象
onRowClick(record: T) => void行点击事件处理函数
onSelectChange(selectedRowKeys: React.Key[], selectedRows: T[]) => void选择变更事件处理函数
(2)填写TableConfig
interface TableConfig {url: string;columns: TableProps<DataType>["columns"];
}
 const tableConfig = useMemo<TableConfig>(() => {return {url: ",rowKey: "",queryParams: ,columns,deleteConfig:{enableDelete: true,confirmMessage: "删除",keyField: "",singleUrl: "",},editConfig:{enableEdit: true,confirmMessage: "",keyField: "",editUrl: "",columns},......};}, [formData]); // 添加formData到依赖数组
(3)批量删除&&添加(如有需要)
  <EnhancedTableonSelectChange={(keys, rows) => {setSelectedRowKeys(keys);setSelectedRows(rows);}}//父子通信选中的行tableConfig={tableConfig}ref={tableRef}//通过ref可以使用到子提供的函数/>

状态管理:

 const [selectedRowKeys, setSelectedRowKeys] = useState<React.Key[]>([]);const [selectedRows, setSelectedRows] = useState<DataType[]>([]);

定义子提供的函数的ref类型

 const tableRef = useRef<{ handleBatchDelete: () => void; handleAdd: () => void }>(null);

定义点击批量删除/添加按钮的函数

  // 调用批量删除const handelBatchDelete = () => {tableRef.current?.handleBatchDelete();};// 调用新增const handelAdd = () => {tableRef.current?.handleAdd();};

使用

   <Button type="primary" onClick={handelAdd}>新增企业</Button><Buttontype="primary"dangerclassName="delete ml"disabled={selectedRowKeys.length ? false : true}onClick={handelBatchDelete}// onClick={handelDelete}>批量删除</Button>
(4)高级功能

表单列配置

interface ColumnConfig {name: string; // 字段名label: string; // 标签名type: 'input' | 'radio' | 'select' | 'textarea'; // 字段类型required?: boolean; // 是否必填rules?: any[]; // 验证规则options?: { value: string; label: string }[]; // 选择类型的选项placeholder?: string; // 占位符span?: number; // 占用列数initialValue?: any; // 初始值
}

行选择功能:

通过设置 rowSelection: true 启用行选择功能,支持单选和多选,可通过 onSelectChange 事件获取选中的行。

http://www.lryc.cn/news/612035.html

相关文章:

  • 思途AOP学习笔记 0806
  • nginx代理出https,request.getRequestURL()得到http问题解决
  • 界面规范的其他框架实现-列表-layui实现
  • TypeError: crypto$2.getRandomValues is not a function
  • 北大、蚂蚁三个维度解构高效隐私保护机器学习:前沿进展+发展方向
  • AlexNet训练和测试CIFAR10
  • Python金融分析:从基础到量化交易的完整指南
  • 如何定位一个高并发场景下API响应时间从200ms突增到2s的问题
  • 生成模型实战 | Transformer详解与实现
  • 需求链路追踪
  • centos配置java环境变量
  • SpringCloud -- elasticsearch(二)
  • MonoFusion 与 Genie 3
  • 如何快速掌握大数据技术?大四学生用Spark和Python构建直肠癌数据分析与可视化系统
  • Apollo中三种相机外参的可视化分析
  • 「iOS」————单例与代理
  • iOS 文件管理实战指南 查看 App 数据与系统日志的完整方法
  • Python虚拟环境完全指南:pyenv vs venv 在macOS上的使用详解
  • SpringBoot 3.x整合Elasticsearch:从零搭建高性能搜索服务
  • Post-train 入门(1):SFT / DPO / Online RL 概念理解和分类
  • 未给任务“Fody.WeavingTask”的必需参数“IntermediateDir”赋值。 WpfTreeView
  • 嵌入式开发学习———Linux环境下IO进程线程学习(五)
  • 【PZSDR P201MINI】 P201Mini 软件无线电开发板:紧凑型射频系统的性能标杆
  • Debian系统更新实现
  • 在 Neo4j实现虚拟关系(间接)的可视化
  • (Python)待办事项升级网页版(html)(Python项目)
  • 识别 Base64 编码的 JSON、凭证和私钥
  • IntelliJ IDEA 2025.1.4.1 中文版
  • 防火墙(firewalld)
  • 医疗AI中GPU部署的“非对等全节点架构“方案分析(中)