1. 关于 ant-pro components
ProComponents 是基于 Ant Design 而开发的模板组件,提供了更高级别的抽象支持,开箱即用。可以显著地提升制作 CRUD 页面的效率,更加专注于页面本身。
ant-pro components 本身也是一个monorepo仓库,如图:
其中,每一个文件夹都代表一个组件,这也就意味着,ProComponents 每一个组件都是一个独立的包。
- ProLayout 解决布局的问题,提供开箱即用的菜单和面包屑功能
- ProTable 表格模板组件,抽象网络请求和表格格式化
- ProForm 表单模板组件,预设常见布局和行为
- ProCard 提供卡片切分以及栅格布局能力
- ProDescriptions 定义列表模板组件,ProTable 的配套组件
- ProSkeleton 页面级别的骨架屏
- ProSkeleton 表单项,集成了常用的表单项,可以把他们当成一个 FormItem来使用
2. 快速搭建通用页面
2.1 搜索项 + 表格
ProTable 在 antd 的 Table 上进行了一层封装,支持了一些预设,并且封装了一些行为。这里只列出与 antd Table 不同的 API。
2.1.1 request
request 是 ProTable 最重要的 API,request 会接收一个对象。对象中必须要有 data 和 success,如果需要手动分页 total 也是必需的。request 会接管 loading 的设置,同时在查询表单查询时和 params 参数发生修改时重新执行。同时查询表单的值和 params 参数也会带入。以下是一个例子
<ProTable<DataType, Params>
// params 是需要自带的参数
// 这个参数优先级更高,会覆盖查询表单的参数
params={params}
request={async (
// 第一个参数 params 查询表单和 params 参数的结合
// 第一个参数中一定会有 pageSize 和 current ,这两个参数是 antd 的规范
params: T & {
pageSize: number;
current: number;
},
sort,
filter,
) => {
// 这里需要返回一个 Promise,在返回之前你可以进行数据转化
// 如果需要转化参数可以在这里进行修改
const msg = await myQuery({
page: params.current,
pageSize: params.pageSize,
});
return {
data: msg.result,
// success 请返回 true,
// 不然 table 会停止解析数据,即使有数据
success: boolean,
// 不传会使用 data 的长度,如果是分页一定要传
total: number,
};
}}
/>
2.1.2 ActionRef 手动触发
有时我们要手动触发 table 的 reload 等操作,可以使用 actionRef
interface ActionType {
reload: (resetPageIndex?: boolean) => void;
reloadAndRest: () => void;
reset: () => void;
clearSelected?: () => void;
startEditable: (rowKey: Key) => boolean;
cancelEditable: (rowKey: Key) => boolean;
}
const ref = useRef<ActionType>();
<ProTable actionRef={ref} />;
// 刷新
ref.current.reload();
// 刷新并清空,页码也会重置,不包括表单
ref.current.reloadAndRest();
// 重置到默认值,包括表单
ref.current.reset();
// 清空选中项
ref.current.clearSelected();
// 开始编辑
ref.current.startEditable(rowKey);
// 结束编辑
ref.current.cancelEditable(rowKey);
2.2 表单
ProForm 在原来的 Form 的基础上增加了一些语法糖和更多的布局设置,帮助我们快速地开发一个表单,同时添加了一些默认行为,让我们的表单默认好用。当你想快速实现一个表单但不想花太多时间去布局时 ProForm 是最好的选择。
ProForm 是基于 antd Form 的可降级封装,与 antd 功能完全对齐,但是在其之上还增加一些预设行为和多种布局。这些布局之间可以无缝切换,并且拥有公共的 API。
2.2.1 ProForm表单
ProForm 封装了很多常见的表单逻辑和布局,学习成本相对较低。团队成员只需要了解一些简单的配置项,就可以快速上手并搭建出表单页面。这对于新手开发者或者对表单开发经验较少的团队来说,可以降低学习门槛,提高开发效率。
- 数据获取:- 支持数据同步和异步处理:可以通过配置
request属性实现异步数据提交。
<ProFormSelect
width="md"
valueEnum={{
red: 'Red',
green: 'Green',
blue: 'Blue',
}}
fieldProps={{
labelInValue: true,
}}
request={async () => [
{ label: '全部', value: 'all' },
{ label: '未解决', value: 'open' },
{ label: '已解决', value: 'closed' },
{ label: '解决中', value: 'processing' },
]}
name="useMode"
label="合同约定生效方式"
/>
2. params:配合 request 属性使用,用于传递请求所需的参数。当表单初始化请求数据或者提交数据时,这些参数会被发送到服务器。
3. submitter 用于配置表单提交按钮的属性和行为,如按钮的文本、样式、是否显示等。可以通过 submitter 属性快速定制提交按钮,而在 antd Form 中需要手动编写提交按钮的代码。
4. ProFormDependency 数据联动:procomponents.ant.design/components/…
5. 还有一些其他的属性方便表单的开发,详细的文档可在官网查看:procomponents.ant.design/components/…
2.3 Schema Form - JSON 表单
chemaForm 是根据 JSON Schema 来生成表单的工具。SchemaForm 会根据 valueType 来映射成不同的表单项。
对于复杂的表单而言,虽然JSON配置化的效率看起来很高,实际中对于查找问题还是有一些不方便的地方,例如关键字的查找可能会定
import type { ProFormColumnsType } from '@ant-design/pro-components';
import {
BetaSchemaForm,
ProForm,
ProFormSelect,
ProFormText,
} from '@ant-design/pro-components';
const valueEnum = {
all: { text: '全部', status: 'Default' },
open: {
text: '未解决',
status: 'Error',
},
closed: {
text: '已解决',
status: 'Success',
disabled: true,
},
processing: {
text: '解决中',
status: 'Processing',
},
};
type DataItem = {
name: string;
state: string;
};
const columns: ProFormColumnsType<DataItem>[] = [
{
title: '标题',
dataIndex: 'title',
formItemProps: {
rules: [
{
required: true,
message: '此项为必填项',
},
],
},
width: 'm',
},
{
title: '状态',
dataIndex: 'state',
valueType: 'select',
valueEnum,
width: 'm',
},
];
export default () => {
return (
<ProForm>
<h1>ProForm </h1>
<ProFormText name="username" />
<ProFormSelect
name="select-multiple"
label="多选"
valueEnum={{
red: 'Red',
green: 'Green',
blue: 'Blue',
}}
fieldProps={{
mode: 'multiple',
}}
placeholder="Please select favorite colors"
rules={[ { required: true, message: 'Please select your favorite colors!', type: 'array', }, ]}
/>
<h1>表单1 </h1>
<BetaSchemaForm<DataItem> layoutType="Embed" columns={columns} />
<h1>表单2</h1>
<BetaSchemaForm<DataItem>
layoutType="Embed"
columns={[ { title: '创建时间', key: 'showTime', dataIndex: 'createName', valueType: 'date', }, { title: '分组', valueType: 'group', columns: [ { title: '状态', dataIndex: 'groupState', valueType: 'select', width: 'xs', valueEnum, }, { title: '标题', width: 'md', dataIndex: 'groupTitle', formItemProps: { rules: [ { required: true, message: '此项为必填项', }, ],
},
},
],
},
]}
/>
</ProForm>
);
};
procomponents.ant.design/components/… 示例
import type { ProFormColumnsType } from '@ant-design/pro-components';
import {
BetaSchemaForm,
ProForm,
ProFormSelect,
ProFormText,
} from '@ant-design/pro-components';
const valueEnum = {
all: { text: '全部', status: 'Default' },
open: {
text: '未解决',
status: 'Error',
},
closed: {
text: '已解决',
status: 'Success',
disabled: true,
},
processing: {
text: '解决中',
status: 'Processing',
},
};
type DataItem = {
name: string;
state: string;
};
const columns: ProFormColumnsType<DataItem>[] = [
{
title: '标题',
dataIndex: 'title',
formItemProps: {
rules: [
{
required: true,
message: '此项为必填项',
},
],
},
width: 'm',
},
{
title: '状态',
dataIndex: 'state',
valueType: 'select',
valueEnum,
width: 'm',
},
];
export default () => {
return (
<ProForm>
<h1>ProForm </h1>
<ProFormText name="username" />
<ProFormSelect
name="select-multiple"
label="多选"
valueEnum={{
red: 'Red',
green: 'Green',
blue: 'Blue',
}}
fieldProps={{
mode: 'multiple',
}}
placeholder="Please select favorite colors"
rules={[ { required: true, message: 'Please select your favorite colors!', type: 'array', }, ]}
/>
<h1>表单1 </h1>
<BetaSchemaForm<DataItem> layoutType="Embed" columns={columns} />
<h1>表单2</h1>
<BetaSchemaForm<DataItem>
layoutType="Embed"
columns={[ { title: '创建时间', key: 'showTime', dataIndex: 'createName', valueType: 'date', }, { title: '分组', valueType: 'group', columns: [ { title: '状态', dataIndex: 'groupState', valueType: 'select', width: 'xs', valueEnum, }, { title: '标题', width: 'md', dataIndex: 'groupTitle', formItemProps: { rules: [ { required: true, message: '此项为必填项', }, ],
},
},
],
},
]}
/>
</ProForm>
);
};
3.ProFormFields 表单项
3.1ProFormFields 的布局
ProFormFields 可以包裹多个不同类型的表单项,以构建复杂的表单。以下示例展示了包含文本输入框、密码输入框和提交按钮的表单:
const ComplexForm = () => {
return (
<ProForm onFinish={(values) => console.log('表单提交值:', values)}>
<ProFormFields>
<ProFormText name="username" label="用户名" />
<ProFormText.Password name="password" label="密码" />
</ProFormFields>
<ProForm.Submit />
</ProForm>
);
};
3.2 与数据请求结合
ProFormFields 可以与 ProForm 的 request 属性结合,实现表单数据的异步加载和提交。以下示例展示了如何在表单初始化时从服务器获取数据,并在表单提交时将数据发送到服务器:
import axios from 'axios';
const fetchData = async () => {
const response = await axios.get('/api/user');
return response.data;
};
const submitData = async (values) => {
await axios.post('/api/user', values);
};
const FormWithRequest = () => {
return (
<ProForm request={fetchData} onFinish={submitData}>
<ProFormFields>
<ProFormText name="username" label="用户名" />
<ProFormText name="email" label="邮箱" />
</ProFormFields>
<ProForm.Submit />
</ProForm>
);
};
3.3 与 Form.Item 的区别
3.1 代码简洁性
- ProFormFields + ProForm 系列组件:ProFormFields 结合 ProForm 提供的各种表单组件(如
ProFormText、ProFormSelect等),代码更加简洁。例如,创建一个简单的文本输入框,只需要一行代码:
<ProFormText name="username" label="用户名" />
- Form.Item + 原生表单控件:使用 Ant Design 的 Form.Item 时,需要手动包裹原生表单控件,代码相对繁琐。例如:
<Form.Item label="用户名" name="username">
<Input />
</Form.Item>
3.2 功能封装
- ProFormFields:ProFormFields 及相关组件封装了许多常见的表单逻辑,如数据验证、数据获取和提交等。例如,通过
rules属性可以轻松设置表单验证规则:
<ProFormText
name="username"
label="用户名"
rules={[{ required: true, message: '请输入用户名' }]}
/>
<Form.Item
label="用户名"
name="username"
rules={[{ required: true, message: '请输入用户名' }]}
>
<Input />
</Form.Item>
虽然两者都能实现验证,但 ProForm 的方式更加简洁。
3.3 布局与样式
- ProFormFields:ProForm 提供了统一的布局和样式设置,如
labelWidth属性可以统一设置表单项标签的宽度,使表单布局更加整齐美观。
<ProForm labelWidth={100}>
<ProFormFields>
<ProFormText name="username" label="用户名" />
<ProFormText name="email" label="邮箱" />
</ProFormFields>
</ProForm>
- Form.Item:使用 Form.Item 时,需要手动调整每个表单项的布局和样式,灵活性较高,但也增加了开发的复杂度。
3.4 高级功能
- ProFormFields:支持许多高级功能,如数据字典、动态表单项等。例如,使用
options属性可以快速设置下拉框的选项:
<ProFormSelect
name="city"
label="城市"
options={[
{ label: '北京', value: 'beijing' },
{ label: '上海', value:'shanghai' },
]}
/>
- Form.Item:实现类似的高级功能需要编写更多的代码和逻辑。
4. 总结
在 admin 管理系统中,几乎风格都是统一的,页面的样式、 布局、以及页面的功能都能达到antd-pro的要求。可实现页面的快速搭建以及功能的统一。官方文档也一直在更新中
参考文章: