封装日常工具函数和Hooks
概述
封装日常使用的工具函数、React组件和Hooks,提高开发效率,避免踩坑
工具函数
过滤参不合法对象属性
清理对象参数值,过滤不合法参数
1 | /** |
时间格式化
格式化时间戳,支持格式化时间区间
1 | /** |
时间区间格式化
格式化时间为开始时间:00:00:00 - 结束时间: 23:59:59
1 | import moment from 'moment'; |
匹配枚举字段值
匹配枚举字段值,针对Table列表格式化显示的辅助工具函数
1 | /** |
数字格式化为千分位
数字格式化为千分位,主要格式化金额
1 | /** |
金额格式化转换
金额格式化转换,针对分转元,元转分的,这里使用了 number-precision 工具包,用于金额的精准计算,避免在小数值计算时产生误差(避免踩坑)
1 | npm install number-precision --save |
1 | import NP from 'number-precision' |
工具包地址:https://github.com/zhaowei-plus/utils-tools
组件
列表搜索组件
List表头搜索组件,一般是和Antd Table配合使用,这里使用了Formily表单库,在使用前需要安装依赖
1 | npm install --save @formily/antd |
Formily官网地址:https://formilyjs.org/#/bdCRC5/dzUZU8il
1 | import React from 'react' |
css 样式如下:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45.search {
display: flex;
flex-wrap: wrap;
justify-content: flex-start;
.ant-form-item {
display: grid;
grid-template-columns: minmax(80px, max-content) auto;
margin-bottom: 0;
&:before {
display: none;
}
.ant-form-item-label {
height: 40px;
line-height: 40px;
padding: 0 10px;
}
.ant-form-item-control-wrapper {
height: 40px;
line-height: 40px;
.ant-calendar-picker,
.ant-select {
width: 100%;
min-width: 200px;
}
}
}
&__actions {
flex: 1;
height: 40px;
display: flex;
justify-content: flex-end;
.button-group {
height: 40px;
line-height: 40px;
width: 140px;
}
}
}
注意Search组件中的schema是Formily的标准schema(Formily Form Schema文档地址)去掉了外部的 properties 配置:1
2
3
4
5
6{
"type": "object",
"properties": {
...schema // 导入的schema配置
}
}
案例:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18() => {
const schema = {
orgName: {
type: 'string',
title: '企业名称/编码'
}
const onSearch = (params) => {
// 根据条件搜索数据
}
return (
<Search
schema={schema}
onSearch={onSearch}
/>
)
}
显示结果:
Hooks
useList
useList hook是组装了表头搜索组件和Table结果数据的hook,通过url和默认参数搜索结果,获取Table数据并显示,具体代码如下:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88import { useState } from 'react'
/**
* useList hook,用于Table、有搜索栏的Table数据搜索
*
* @param {string} url 请求地址
* @param {object} initialParams 初始化参数,初始化时需要有搜索参数,并且在后续搜索中可以被修改的参数
* @param {object} staticParams 静态参数,每次搜索都固定不变的参数
* */
export default (url, initialParams = {}, staticParams = {}) => {
const [params, setParams] = useState(initialParams)
const [dataSource, setDataSource] = useState([])
const [pagination, setPagination] = useState({
current: 1,
pageSize: 10,
total: 0,
showQuickJumper: true,
showTotal: total => `共${total}条`
})
/*
* 查询列表信息:
* 1 刷新时,分页器不变,搜索参数不变
* 2 查询时,分页器清零,搜索参数改变
* */
const onFetch = (_pagination = pagination, _params = params) => {
const { current: currentPage, pageSize } = _pagination
const data = {
pageIndex: currentPage,
pageNo: currentPage,
pageSize,
..._params,
...staticParams
}
/**
* 向后端发送请求列表数据的方法根据项目实际自定义实现,主要
* 是针对不同项目请求方式的不同做兼容处理
* 注意:这里的请求没有写死,主要是因为很多项目中的请求方式不一样,使用时可以拷贝自行替换
* */
http.get(url, {
pageIndex: currentPage,
pageNo: currentPage,
pageSize,
..._params,
...staticParams
}).then((res) => {
const { rows = [], total } = res.data || {}
setDataSource(rows)
setParams(_params)
setPagination({
..._pagination,
total,
current: currentPage
})
})
}
/**
* 参数查询列表信息
* */
const onSearch = (_params) => {
onFetch({ ...pagination, current: 1}, _params)
}
/**
* 分页查询列表信息
* */
const onChange = (_pagination) => {
onFetch(_pagination)
}
return {
params,
onSearch,
onFetch,
// table所需要的值
table: {
pagination,
dataSource,
onChange,
},
}
}
案例:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22() => {
const list = useList('serviceOrder/list')
const onSearch = (params) => {
list.onSearch(params)
}
useEffect(() => {
list.onFetch() // 搜索数据
}, [])
// 有时候需要列表搜索的参数,可以取值 list.params
const columns = [/** Table列表项 **/]
return (
<Table
columns={columns}
{...list.table}
/>
)
}
useTable
useTable 是基于useList 的简单封装,返回Table数据和XmTable组件,不需要导入Antd的Table,代码如下:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26import React from 'react'
import { Table} from 'antd'
import useList from './use-list'
export default (url, initialParams = {}, staticParams = {}) => {
const list = useList(url, initialParams, staticParams)
const XmTable = (props) => {
const { rowKey = 'id', columns = [], ...rest } = props
return (
<Table
rowKey={rowKey}
columns={columns}
{...list.table}
{...rest}
/>
)
}
return {
table: list,
XmTable
}
}
案例:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21() => {
const { table, XmTable } = useTable('serviceOrder/list')
const onSearch = (params) => {
table.onSearch(params)
}
useEffect(() => {
table.onFetch() // 搜索数据
}, [])
// 有时候需要列表搜索的参数,可以取值 table.params
const columns = [/** Table列表项 **/]
return (
<XmTable
columns={columns}
/>
)
}
useSearchTable
useSearchTable 是基于封装了Search组件和useTablehook,返回Table数据和SearchTable组件,代码如下:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45import React, {useState, Fragment, useEffect} from 'react'
import useTable from './use-table'
import Search from "../Search"
export default (url, initialParams = {}, staticParams = {}) => {
const [ initialValues, setInitialValues ] = useState(initialParams)
const { table, XmTable } = useTable(url, initialParams, staticParams)
const SearchTable = (props) => {
const { schema, columns = [], onSearch, ...rest } = props
const handleSearch = (params = initialParams) => {
setInitialValues(params)
table.onSearch(typeof onSearch === 'function' ? onSearch(params) : params)
}
return (
<Fragment>
<div className="app-page__card">
<Search
schema={schema}
onSearch={handleSearch}
initialValues={initialValues}
/>
</div>
<div className="app-page__card">
<XmTable
columns={columns}
{...rest}
/>
</div>
</Fragment>
)
}
useEffect(() => {
table.onSearch(initialParams)
}, [])
return {
table,
SearchTable,
}
}
案例:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15() => {
const { table, SearchTable } = useSearchTable('serviceOrder/list')
// 有时候需要列表搜索的参数,可以取值 table.params
const schema = { /** Search搜索项 **/ }
const columns = [/** Table列表项 **/]
return (
<SearchTable
schema={schema}
columns={columns}
/>
)
}
useVisible
useVisible 是对Antd Modal封装的hook,可以更方便的open/close,代码如下:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27import { useState, useCallback } from 'react'
/**
* 自定义 hook:用于弹出框的打开与关闭控制
*
* @param {boolean} initVisible 初始化modal的显示状态
*/
export default (initVisible = false) => {
const [params, setParams] = useState()
const [visible, setVisible] = useState(initVisible)
const open = useCallback((_params) => {
setParams(_params)
setVisible(true)
}, [])
const close = useCallback(() => {
setParams()
setVisible(false)
}, [])
return {
params,
visible,
open,
close,
}
}
案例:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23() => {
const editModal = useVisible()
const opem = (orderId) => {
// open 传递的参数
editModal.open(orderId)
}
return (
{
editModal.visible && (
<EditModal
orderId={editModal.params}
onCancel={editModal.close}
onOk={() => {
editModal.close()
table.onFetch()
}}
/>
)
}
)
}
Hooks包地址:https://github.com/zhaowei-plus/utils-hooks
其他
更多自定义Hooks可以查看umijs Hooks封装