实现常规的form table 分页的封装
说明:根据项目情况更改分页参数useCommonHook文件中的pageObj 参数和BaseTable用到的分页参数
useCommonHook文件中如果没有使用@reduxjs/toolkit可以改为
yarn add nanoid
然后import { nanoid } from “nanoid”;
一定要使用nanoid不然无法刷新 或者用时间戳
- 示例用法 组件用法
import { axios } from "@/common/request";
import { Space } from "antd";
import BaseTable from "@/components/BaseTable";
import { Form, Input, Button, Modal } from "antd";
import { useState } from "react";
const columns = [
{
title: "主单号",
dataIndex: "cgid",
},
{
title: "分单号",
dataIndex: "SubOrderNo",
},
{
title: "货物RFID",
dataIndex: "Cargorfid",
},
{
title: "Action",
key: "action",
render: (text, record) => (
<Space size="middle">
<a>Invite {record.Status}</a>
<a>Delete</a>
</Space>
),
},
];
const formItem = [
<Form.Item className="baseTable_form_item" label="姓名" name="username">
<Input />
</Form.Item>,
<Form.Item className="baseTable_form_item" label="年纪" name="age">
<Input />
</Form.Item>,
<Form.Item className="baseTable_form_item" label="学校" name="school">
<Input />
</Form.Item>,
<Form.Item className="baseTable_form_item" label={<Input />} name="school">
<Input />
</Form.Item>,
];
let refresh = null;
const Home = () => {
const [modelShow, setModelShow] = useState(false);
const getList = (params = { pageindex: 0, pagesize: 30 }, tableRefresh) => {
refresh = tableRefresh;
return axios.get("/api/sinoapi/getcargolist", {
pageindex: 0,
pagesize: 30,
...params,
});
},
complete = (list) => {
list.forEach((item) => {
item.name = item.name + item.age;
});
return list;
};
return (
<>
<BaseTable
formItem={formItem}
initialValues={{ username: "ss" }}
formProps={{}}
search={getList}
complete={complete}
columns={columns}
tableProps={{
rowKey: "Cargorfid",
}}
>
{}
<Button
type="primary"
onClick={() => {
setModelShow(true);
}}
>
导出
</Button>
<Button type="primary">导出</Button>
<Button type="primary">导出</Button>
<Button type="primary">导出</Button>
<Button type="primary">导出</Button>
<Button type="primary">导出</Button>
</BaseTable>
{}
<Modal
title="Basic Modal"
visible={modelShow}
onOk={() => {
refresh(true);
setModelShow(false);
}}
onCancel={() => {
refresh(false);
setModelShow(false);
}}
>
<p>Some contents...</p>
<p>Some contents...</p>
<p>Some contents...</p>
</Modal>
</>
);
};
export default Home;
- 封装的BaseTable 组件
import classNames from "classnames";
import { Form, Button, Table, Pagination } from "antd";
import "./index.less";
import {
useFormItemKey,
useButtonMargin,
useTableAxios,
} from "./useCommonHook";
import { useCallback, useState } from "react";
const BaseTable = ({
formItem = [],
initialValues = {},
formProps = {},
search,
columns = [],
tableProps = {},
children,
complete = null,
}) => {
const [form] = Form.useForm();
const [formItemKeys] = useFormItemKey(formItem);
const [childrenMargin] = useButtonMargin(children);
const [loading, setLoading] = useState(false);
const tableRefresh = useCallback((form, dispatch) => (refresh) => {
if (refresh) {
form.resetFields();
dispatch({ type: "reset" });
return;
}
dispatch({ type: "refresh" });
});
const searchCommon = (values, params, dispatch, setList) => {
setLoading(true);
search({ ...values, ...params }, tableRefresh(form, dispatch))
.then(({ success, result }) => {
setLoading(false);
if (!success) return;
if (complete) {
const arrs = complete(result?.data ?? []);
setList(arrs);
}
setList(result?.data ?? []);
dispatch({ type: "total", payload: result?.total ?? 0 });
})
.catch((e) => {
console.log("=======列表请求失败========" + e);
setLoading(false);
});
};
const [list, dispatch, params, setList] = useTableAxios(form, searchCommon);
const paginationChange = useCallback((page, pageSize) => {
dispatch({ type: "pageindex", payload: page });
dispatch({ type: "pagesize", payload: pageSize });
});
const onFinish = useCallback((values) => {
searchCommon(values, params, dispatch, setList);
});
return (
<div>
<div className={classNames("baseTable_padding", "baseTable_form")}>
{}
<Form
initialValues={{ ...initialValues }}
form={form}
name="basicForm"
labelCol={{ span: 8 }}
wrapperCol={{ span: 16 }}
onFinish={onFinish}
autoComplete="off"
layout="inline"
{...formProps}
>
{formItemKeys}
<Form.Item
wrapperCol={{ offset: 8, span: 16 }}
className="baseTable_form_item"
>
<Button type="primary" htmlType="submit">
搜索
</Button>
</Form.Item>
<Form.Item
wrapperCol={{ offset: 8, span: 16 }}
className="baseTable_form_item"
>
<Button
htmlType="button"
onClick={() => {
tableRefresh(form, dispatch)(true);
}}
>
重置
</Button>
</Form.Item>
</Form>
</div>
<div style={{ padding: "15px" }}>{childrenMargin}</div>
<div className={classNames("baseTable_padding", "baseTable_form")}>
<Table
columns={columns}
dataSource={list}
pagination={false}
loading={loading}
{...tableProps}
/>
<Pagination
className="baseTable_pagination"
showTotal={(total) => `共 ${total} 条`}
showQuickJumper
current={params.pageindex}
total={params.total}
onChange={paginationChange}
/>
</div>
</div>
);
};
export default BaseTable;
- 用得到的自定义useCommonHook
import { useState, useEffect, cloneElement, Children, useReducer } from "react";
import { nanoid } from "@reduxjs/toolkit";
export const useFormItemKey = (formItem) => {
const [formItemKeys, setFormItemKeys] = useState([]);
useEffect(() => {
const result = Children.map(formItem, (item) =>
cloneElement(item, { key: nanoid() })
);
setFormItemKeys(result);
}, [formItem]);
return [formItemKeys];
};
export const useButtonMargin = (children) => {
const [childrenMargin, setchildrenMargin] = useState([]);
useEffect(() => {
const result = Children.map(children, (item) =>
cloneElement(item, { key: nanoid(), style: { marginRight: "15px" } })
);
setchildrenMargin(result);
}, [children]);
return [childrenMargin];
};
export const pageObj = {
pageindex: 1,
pagesize: 10,
total: 0,
reset: nanoid(),
};
export const reducer = (state, action) => {
switch (action.type) {
case "total":
return { ...state, total: action.payload };
case "pageindex":
return { ...state, pageindex: action.payload };
case "pagesize":
return { ...state, pagesize: action.payload };
case "reset":
return { ...state, ...pageObj, reset: nanoid() };
case "refresh":
return { ...state, reset: nanoid() };
}
};
export const useTableAxios = (form, searchCommon) => {
const [list, setList] = useState([]);
const [params, dispatch] = useReducer(reducer, pageObj);
useEffect(() => {
const timeout = setTimeout(() => {
const values = form.getFieldsValue();
searchCommon(values, params, dispatch, setList);
}, 0);
return () => {
clearTimeout(timeout);
};
}, [params.pageindex, params.pagesize, params.reset]);
return [list, dispatch, params, setList];
};
- 依赖的css index.less
.baseTable_form {
background: white;
}
.baseTable_padding {
padding: 0px 15px 15px 15px;
}
.baseTable_form_item {
margin-top: 15px;
}
.baseTable_pagination {
margin-top: 15px;
text-align: right;
}