今天分享一篇关于ProComponents (ant.design)的文章,后面也会围绕ProTable这个组件去更新一个比较好用的table。
这次主要用到的技术点:
import { createContext, useEffect } from 'react';
import { useRef, useState } from 'react';
import ProTable from '@ant-design/pro-table';
import { createContext, useEffect } from 'react';
import { useRef, useState } from 'react';
import type { ActionType, ProColumnType } from '@ant-design/pro-table';
import ProTable from '@ant-design/pro-table';
import { Space, Table } from 'antd';
import type { AlertRenderType } from '@ant-design/pro-table/lib/components/Alert';
import { history } from 'umi';
import type { SizeType } from '@ant-design/pro-form/lib/BaseForm';
import type { SearchConfig } from '@ant-design/pro-table/lib/components/Form/FormRender';
//定义当前组件接受的参数以及定义的类型
type CustomTableProps
title?: string | JSX.Element[];
filter?: string | JSX.Element[];
columns?: ProColumnType
toolBarComponents?: JSX.Element[];
tableAlertOptionRender?: AlertRenderType
hideOptions?: boolean;
reload?: boolean;
pagination?: boolean;
tableActionRef?: React.MutableRefObject
dataRow?: T;//这个参数一般用不到,使用到特殊需求的,例如翻译字段,当请求数据只返回code,需要去翻译中文的时候 可以使用此字段来改变当前某一行数据的发生变化
search?: false | SearchConfig;//table是否带搜索字段,官网默认的ProTable自带搜索,不需要可以设置为false
queryPage?: (params: Partial) => Promise<{ success: boolean; total: number; data: T[] }>;
queryPage这个字段是用来传接口使用的 官网给的有一个api:{request}是用来请求数据的 我们可以把接口传递进去 让组件去完成,
tableSearchParams?: any;
defaultSort?: string[];
defaultSize?: SizeType;
};
//这个方法可以当作回调去处理,比如我们在自定义搜索的时候可以使用其方法的去调用和刷新接口,自定义搜索我们下一章再贴出来
export const NpTableContext = createContext<{
actionRef?: React.MutableRefObject
onSearhParamsChanged?: (params: any) => void;
}>({});
const CustomTable =
const {
title,
filter,
columns,
hideOptions,
tableActionRef,
toolBarComponents,
tableAlertOptionRender,
dataRow,
sourceRow,
queryPage,
tableSearchParams,
search,
defaultSort,
defaultSize,
reload = true,
pagination = false
} = props;
const currentPathName = history.location.pathname;
const initColumnsState = localStorage.getItem(currentPathName) ? JSON.parse(localStorage.getItem(currentPathName)!.toString()) : undefined;
const [dataSource, setDataSource] = useState
const [searchParams, setSearchParams] = useState
const [currentPage, setCurrentPage] = useState
useEffect(() => {
if (dataRow) {
setDataSource(dataSource.map(x => {
if (x.id === dataRow.id) {
return { ...dataRow }
} else {
return x;
}
}))
}
// eslint-disable-next-line react-hooks/exhaustive-deps
//dataRow 需要对某一条数据修改可以是用这个方法 更新dataSource
}, [dataRow])
useEffect(() => {
if (sourceRow) {
setDataSource(sourceRow)
}
// eslint-disable-next-line react-hooks/exhaustive-deps
//dataRow 需要对整个table数据修改可以是用这个方法 更新dataSource
}, [sourceRow])
const onSearhParamsChanged = (params: Partial) => {
//搜索
const newParams = { ...searchParams, ...params };
setSearchParams(newParams);
}
const actionRef = useRef
//调用table的方法
return (
actionRef: tableActionRef || actionRef, onSearhParamsChanged: onSearhParamsChanged }}> style={{ padding: 0, margin: 0 }} rowKey='id' dataSource={dataSource} defaultSize={defaultSize} pagination={ pagination ? { showSizeChanger: false, current: currentPage } : { showSizeChanger: true, onShowSizeChange: (current, size) => { setCurrentPage(current) localStorage.setItem(currentPathName + '/pageSize', size.toString()); }, pageSize: Number(localStorage.getItem(currentPathName + '/pageSize')) || 10, current: currentPage } } toolBarRender={ (toolBarComponents) ? () => [toolBarComponents,] : false } search={(search) || false} toolbar={{ title: (title) ? title : '', filter: (filter) ? filter : '' }} //rowSelection 例如我们对table有复选框之类的操作可以加上这段 rowSelection={tableAlertOptionRender ? { selections: [Table.SELECTION_ALL, Table.SELECTION_INVERT], } : false} tableAlertRender={({ selectedRowKeys, onCleanSelected }) => ( 已选 {selectedRowKeys.length} 项 取消选择 )} tableAlertOptionRender={tableAlertOptionRender} //options=false的时候 是不显示操作栏 options={ hideOptions ? false : { density: true, fullScreen: true, reload: reload, search: false, setting: { }, } } actionRef={tableActionRef || actionRef} columns={columns} //columnsState 针对列的设置 columnsState={{ defaultValue: initColumnsState, persistenceType: 'localStorage', persistenceKey: currentPathName, }} params={tableSearchParams || searchParams} request={async (params: any, sorter) => { const sort = sorter ? JSON.stringify(sorter) .replaceAll('"', '') .replaceAll('{', '') .replaceAll('}', '') .replaceAll('end', '') .replaceAll(':', ',') : undefined; const reqParams = { ...params, page: params.current - 1, size: params.pageSize, sort: [sort, defaultSort || undefined], }; const result = await queryPage?.(reqParams); setDataSource(result?.data || []) return { success: result?.success, data: result?.data, total: result?.total } }} 设置固定列 scroll={{ x: 'max-content' }} />
);
};
export default CustomTable;
使用方法:
方法一:
const tableAttribute = {
columns: tagInfoColumns,
toolBarComponents: [
queryPage: (params: Partial
defaultSort: ['modifiedAt,desc'],
}
方法二:
这样传是因为某些特殊情况下 我们需要把拿到的数据处理后才能渲染,如果我们再组件内处理 会导致复用性比较差 所以再父组件内处理好 传入table组件 可以使组件复用性最大化 我们既可以传入储存的数据又可以使用ProTable中的操作栏
const tableAttribute = {
columns: orderColumns,
toolBarComponents: [],
queryPage: async (params: Partial
const result = await getOrderRequest.queryPage({ ...params, orderType: 'ADJ' })
if (result.success) {
handleCompanyListData();
getFiltered(result.data)
}
return {
data: result.data,
success: result.success,
total: result.total,
}
},
defaultSort: ['modifiedAt,desc'],
sourceRow: dataRow,
}
需求不是很复杂的情况下 官网给的api足够使用 大多数方法都是根据官网给的例子去延申的,下一章贴出针对ProTable组件的 自定义搜索,很多方法还没有写出来 官网给的例子 这个组件基本都支持,在这里就不贴出来了