写这个题目有点标题党的嫌疑,但实际其实也相差无几,下面看真假
介绍
一般后台管理页面都会有增删改查,而增删改查就不可避免有搜索+Table展示。
为了避免写重复的代码,之前封装了Filter
组件,继而又封装TableProps
,并整合在一起,就有了下面的TablePro
封装
- 先看
TableProps
的封装
/** 第三方库 */
import React, { memo, useState } from "react";
/** 第三方组件 */
import { Table } from "antd";
function areEqual(preProps, nextProps) {
return preProps === nextProps;
}
const initPage = {
current: 1,
pageSize: 10
};
// 页面--代码
export default memo(
({
rowKey,
rowSelection,
columns,
dataSource,
pagination,
total,
onPageChange,
...props
}) => {
const [pageParams, setPageParams] = useState(initPage);
const onChange = (page, size) => {
setPageParams({
current: page,
pageSize: size
});
onPageChange(page, size);
};
// 分页器
const paginationProps = {
...pageParams,
total,
showSizeChanger: true,
showQuickJumper: true,
defaultPageSize: 10,
hideOnSinglePage: false,
pageSizeOptions: ["10", "20", "40"],
onChange: (page, size) => onChange(page, size),
onShowSizeChange: (page, size) => onChange(page, size),
showTotal: () => (
<span style={{ float: "left" }}>
{`共 ${total} 条记录 第${pageParams.current}/${Math.ceil(
total / pageParams.pageSize
)}页`}
</span>
)
};
return (
<Table
{...props}
rowSelection={rowSelection}
pagination={pagination || paginationProps}
rowKey={rowKey || "id"}
columns={columns}
dataSource={dataSource || []}
/>
);
},
areEqual
);
上面只是基于日常需求的简单封装,但相信也能满足大部分场景了。
- 下面再结合SearchForm组件整合封装
/** 第三方库 */
import React from "react";
import { debounce } from "lodash"; // 防抖
/** 第三方组件 */
import { Spin } from "antd";
import { SearchForm } from "@/components";
import TableProps from "./TableProps";
// 页面--代码
export default ({
extra, // 额外内容,如外标签等,ReactNode类型
reset = true, // 是否需要重置按钮
autoSearch, // 是否自动触发搜索
loading, // loading 效果
rowKey, // table的rowkey
filterParams, // 查询条件,具体查看SearchForm
total, // table的total
columns, // table的columns
dataSource, // table的dataSource
rowSelection, // table的rowSelection
onSearch, // 点击查询按钮
stopPagination, // 是否符合查询条件,可以用来disabled分页器
onPageChange, // 分页器change事件
...moreProps
}) => {
return (
<Spin spinning={loading} tip="Loading...">
<SearchForm
reset={reset}
extra={extra}
autoSearch={autoSearch}
searchList={filterParams}
stopPagination={debounce(e => stopPagination && stopPagination(e), 350)}
onSearch={debounce(e => onSearch && onSearch(e), 350)}
{...moreProps}
/>
<TableProps
rowKey={rowKey || "id"}
total={total}
columns={columns}
dataSource={dataSource}
rowSelection={rowSelection}
onPageChange={(page, size) => onPageChange && onPageChange(page, size)}
{...moreProps}
/>
</Spin>
);
};
如果看过之前的SearchForm
封装Antd搜索栏组件SearchForm的封装/使用,会看见当前的SearchForm多了extra参数,这个extra是为了在搜索栏的搜索/重置
后添加新的如别的按钮等功能的。
使用
/** 第三方库 */
import React, { useState, useEffect } from "react";
import { connect } from "dva";
/** 第三方组件 */
import { message } from "antd";
import TablePro from "@/components/Table/TablePro";
import redirect from "@/utils/redirect";
import { mobilePattern } from "@/utils/pattern";
import { searchList, columns } from "./initData";
const initPage = {
pageNum: 1,
pageSize: 10
};
// 原料类目页面--代码
export default connect(({ cashbacklist, loading }) => {
return {
...cashbacklist,
loading: !!loading.models.cashbacklist
};
})(({ list, total, loading, dispatch }) => {
const [pageParams, setPageParams] = useState(initPage);
useEffect(() => {
// eslint-disable-next-line no-use-before-define
getList();
}, [pageParams]);
// 获取列表
const getList = async () => {
if (pageParams && pageParams.pageNum && pageParams.pageSize) {
await dispatch({
type: "cashbacklist/fetchList",
payload: {
...pageParams
}
});
}
};
/** 查询 */
const onSearch = val => {
if (val.mobile && !mobilePattern.test(val.mobile)) {
return message.error("请输入正确手机号码");
}
setPageParams({
...val,
pageNum: pageParams.pageNum,
pageSize: pageParams.pageSize
});
};
// columns添加操作
columns[6] = {
title: "操作",
dataIndex: "operate",
key: "operate",
render: (text, record) => {
// console.log(text, record)
const str = `formulaCode=${record.formulaCode}&userName=${
record.userName
}&mobile=${record.mobile}`;
return (
<a
href="#"
onClick={() => {
const pageKey = Math.random();
redirect({
key: pageKey,
name: "详情",
path: `/xxx/xxx?${str}`
});
}}
style={{ marginRight: "10px" }}
>
详情
</a>
);
}
};
// 分页change
const onPageChange = (page, size) => {
setPageParams({
pageNum: page,
pageSize: size
});
};
return (
<TablePro
rowKey="formulaId"
loading={loading}
filterParams={searchList}
onSearch={e => onSearch(e)}
onPageChange={(page, size) => onPageChange(page, size)}
total={total}
columns={columns}
dataSource={list}
/>
);
});
看最后的代码,如果不用组件封装的方式,代码量绝对在300行+。
当然这个组件还可以根据业务再次封装,甚至把接口请求等也封装进去,但我个人比较推崇
组件纯净
,所以我并没有封装具体的业务逻辑到TablePro
中。
TablePro
包括内部的SearchForm
和TableProps
都只是简单的封装,当然还会有很多问题,比如性能优化、比如更好的需求兼容等等。
本文主要是提供一种思路,如果有更好的建议,欢迎在评论中指出。
感谢阅读~
网友评论