React通过hook实现封装表格常用功能
作者:sanhuamao
这篇文章主要为大家详细介绍了React通过hook封装表格常用功能的使用,文中的示例代码讲解详细,具有一定的借鉴价值,有需要的小伙伴可以参考下
封装内容
- 配置分页:usePagination
- 生成过滤项:useFilter
- 获取表格选择配置:useSelect
- 生成批量删除按钮:useDelete
- 生成模态框:useModal
基于react@18.2.0,antd@5.12.5
示例
render部分:
<React.Fragment> <Form layout="inline"> {DeleteEle} {FilterEles} </Form> <Table {...{ columns, dataSource: list || [], rowSelection, pagination: paginationConfig, rowKey: 'inform_uuid', }} /> {ModalEle} </React.Fragment>
效果:
完整代码
import React, { useState, useEffect } from 'react'; import { Form, Table, Tag } from 'antd'; import Detail from './Detail'; // 详情弹框的内容 import { LIST_RES } from '../store'; // 模拟请求数据 import TableGenerator from '../TableGenerator'; // 封装的钩子 const { useFilter, usePagination, useSelect, useDelete, useModal } = TableGenerator; const TestTable = () => { // 1. 生成过滤项。 // 传入配置,可以自行扩展。目前支持输入框、日期范围选择器、普通选择器 // FilterEles:过滤项表单项 // filterRefresh:暴露出来告诉外层需要重新获取数据了 const { FilterEles, filter, filterRefresh } = useFilter([ { name: 'name', // 字段 label: '平台名称', // placeholder type: 'inputString', // 组件类型:字符串输入框 }, { name: 'status', label: '状态', type: 'select', // 组件类型:选择器 initValue: 0, // 默认数据(可选) options: [ { value: 0, label: '全部状态' }, { value: 1, label: '成功' }, { value: 2, label: '失败' }, ], }, { name: ['start_date', 'end_date'], label: ['开始日期', '结束日期'], type: 'dateRange', // 组件类型:日期选择器 }, ]); // 2. 获取分页配置。 // pagination:{page,pageSize,total} // pageRefresh:暴露出来告诉外层需要重新获取数据了 // paginationConfig:作为表格的分页属性 const { pagination, setPagination, pageRefresh, paginationConfig } = usePagination(); // 3. 表格选中配置 // selectedKeys: Array<string> // rowSelection: 作为表格的选择属性 const { selectedKeys, setSelectedKeys, rowSelection } = useSelect(); // 4. 配置模态框。 // 传入数组,用于配置所有弹框类型(详情、添加、编辑等),目前只支持详情,可自行扩展 // ModalEle: 模态框组件 // modal: {isShow:boolean, action:string, record:any} const { ModalEle, modal, setModal } = useModal([ { title: '详情', // 弹框标题 action: 'detail', // 弹框类型 getComponent: (record) => <Detail data={record} />, // 弹框数据 // ... 可以继续添加属性,其他属性将会应用到Modal中 比如footer、handleOk }, ]); // 5. 批量删除按钮,需要搭配useSelect使用 const [DeleteEle] = useDelete({ url: 'ajax/deleteItem.json', data: { uuids: selectedKeys, }, success: () => { // 可选,删除成功后还需要调用的内容 setSelectedKeys([]); getList(); }, keys: selectedKeys, // 用于判断按钮是否可点击 }); const [list, setList] = useState([]); const getList = () => { // 请求数据, 可传入filter和pagination作为参数 Ajax.ajax({ url: 'GetSmsInformList', data: { page: pagination.page, pageSize: pagination.pageSize, filter }, success: (data) => { setList(data.list); setPagination({ ...pagination, page: data.page, total: data.total }); } }); // 模拟数据 // const data = LIST_RES.data; // setList(data.list); // setPagination({ // ...pagination, // page: data.page, // total: data.total, // }); }; // 触发刷新:修改page、pageSize、点击查询、重置时将会触发 useEffect(() => { getList(); }, [pageRefresh, filterRefresh]); const columns = [ { title: '序号', width: 50, align: 'center', render: (v, r, index) => index + 1 + (pagination.page - 1) * pagination.pageSize, }, { title: '平台名称', width: 180, dataIndex: 'req_psname', }, { title: '请求时间', width: 140, dataIndex: 'inform_time', }, { title: '通知对象', width: 180, dataIndex: 'inform_pnumbers', render: (v) => v.join(', '), }, { title: '通知内容', width: 200, dataIndex: 'inform_content', }, { title: '通知结果', width: 80, dataIndex: 'inform_result', render: (v) => v === 0 ? ( <Tag color="#87d068">成功</Tag> ) : ( <Tag color="#f50">失败</Tag> ), }, { title: '操作', width: 60, render: (v, record) => ( <React.Fragment> <a onClick={() => { setModal({ action: 'detail', isShow: true, record, }); }} > 详情 </a> </React.Fragment> ), }, ]; return ( <React.Fragment> <Form layout="inline"> {DeleteEle} {FilterEles} </Form> <Table {...{ scroll: { x: 1170, y: '70vh' }, columns, dataSource: list || [], rowSelection, pagination: paginationConfig, rowKey: 'inform_uuid', }} /> {ModalEle} </React.Fragment> ); }; export default TestTable;
Hook封装
usePagination
配置表格的分页功能
const usePagination = () => { // 默认数据 const [pagination, setPagination] = useState({ page: 1, pageSize: 10, total: 0, }); // 用于触发外层的刷新 const [pageRefresh, setPageRefresh] = useState(false); const config = { size: "small", showQuickJumper: false, total: pagination.total, current: pagination.page, showSizeChanger: true, onChange: (current) => { setPagination({ ...pagination, page: current, }); setPageRefresh(() => !pageRefresh); // 修改页数后,通知外层刷新 }, pageSize: pagination.pageSize, onShowSizeChange: (page, pageSize) => { setPagination({ page, pageSize, }); setPageRefresh(() => !pageRefresh);// 修改页码后,通知外层刷新 }, }; return { pagination, pageRefresh, setPagination, paginationConfig: config, }; };
useSelect
配置表格的选择功能
const useSelect = () => { const [selectedKeys, setSelectedKeys] = useState([]); const rowSelection = { onChange: (selectedKeys) => { setSelectedKeys(selectedKeys); }, selectedRowKeys: selectedKeys, }; return { selectedKeys, rowSelection, setSelectedKeys }; };
useDelete
配置表格的批量删除按钮
const useDelete = ({ url = "", data = {}, success = null, keys = [] }) => { const handleDel = () => { // 请求.. message.success("删除成功"); success && success(); // }; const DeleteEle = ( <React.Fragment> { /**OPER.isDelete : 当有权限时才显示 */} {OPER.isDelete && ( <Form.Item> {keys.length === 0 ? ( <Button icon={<DeleteOutlined />} size="small" disabled> 批量删除 </Button> ) : ( <Popconfirm title="批量删除" description="你确定要删除吗?" okText="确定" cancelText="取消" onConfirm={handleDel} > <Button type="primary" danger icon={<DeleteOutlined />} size="small" > 批量删除 </Button> </Popconfirm> )} </Form.Item> )} </React.Fragment> ); return [DeleteEle]; };
useFilter
配置过滤项,附带查询、重置按钮
import { initFilter, getFormItem } from "./utils"; // 根据配置配置初始化filter数据 ; 根据配置获取组件 const useFilter = (config = []) => { const [filter, setFilter] = useState(initFilter(config)); const [refresh, setRefresh] = useState(false); // 重置过滤项 const handleResetFilter = () => { setFilter(initFilter(config)); setRefresh(!refresh); // 通知外层刷新 }; // 触发查询 const handleSearch = () => { setRefresh(!refresh); // 通知外层刷新 }; // 修改日期类型 const handleDateChange = ([startField, endField], [startTime, endTime]) => { setFilter({ ...filter, [startField]: startTime, [endField]: endTime }); }; // 修改input 类型 const handleInputChange = (e) => { const { name, value } = e.target; setFilter({ ...filter, [name]: value }); }; // 修改select 类型 const handleSelectChange = (name, value) => { setFilter({ ...filter, [name]: value }); }; // 根据配置生成表单项 const FormItemEles = getFormItem(config, { filter, handleInputChange, handleSelectChange, handleDateChange, }); const HandlerEles = [ <Form.Item> <Button type="primary" size="small" onClick={handleSearch} icon={<SearchOutlined />} > 查询 </Button> </Form.Item>, <Form.Item> <Button type="primary" size="small" onClick={handleResetFilter} icon={<ReloadOutlined />} > 重置 </Button> </Form.Item>, ]; return { filter, FilterEles: [...FormItemEles, ...HandlerEles], filterRefresh: refresh, }; };
initFilter:根据不同类型初始化filter数据
const initFilter = (arr) => { const obj = {}; arr.forEach((item) => { switch (item.type) { case "inputString": obj[item.name] = item.initValue || ""; break; case "select": obj[item.name] = item.initValue || 0; break; case "dateRange": item.name.forEach((name) => { obj[name] = ""; }); break; default: break; } }); return obj; };
getFormItem:根据不同的类型生成表单项组件
const getFormItem = ( arr, { filter, handleInputChange, handleSelectChange, handleDateChange } ) => { const Eles = []; arr.forEach((item) => { const name = item.name; const label = item.label; const value = filter[name]; switch (item.type) { case "inputString": Eles.push( <Form.Item> <Input size="small" placeholder={label} name={name} value={value} onChange={handleInputChange} /> </Form.Item> ); break; case "select": Eles.push( <Form.Item> <Select size="small" style={{ width: 120 }} onChange={(v) => { handleSelectChange(name, v); }} name={name} value={value} options={item.options} /> </Form.Item> ); break; case "dateRange": Eles.push( <Form.Item> <RangePicker onChange={(dates) => { handleDateChange(name, dates); }} value={[filter[name[0]], filter[name[1]]]} placeholder={label} size="small" /> </Form.Item> ); default: break; } }); return Eles; };
useModal
配置模态框
const useModal = ( config = [ { title: "详情", action: "detail", getComponent: (record)=><div>详情</div>, }, ] ) => { const [modal, setModal] = useState({ isShow: false, record: null, action: "", }); const handleCancel = () => { setModal({ isShow: false, record: null, action: "", }); }; //对话框信息 let modalProps = { open: modal.isShow, onCancel: handleCancel, maskClosable: false, footer: null, }; const currentModal = config.find((item) => item.action === modal.action); // 找到当前模态框数据 if (currentModal) { const { action, getComponent, ...other } = currentModal; // 配置传进来的其余属性 modalProps = { ...modalProps, ...other, }; } const ModalEle = ( <Modal width="80%" {...modalProps}> {currentModal && currentModal.getComponent(modal.record)} </Modal> ); return { ModalEle, modal, setModal }; };
源码
以上就是React通过hook实现封装表格常用功能的详细内容,更多关于React hook封装表格常用功能的资料请关注脚本之家其它相关文章!