巨型表单慎用,封装此组件的目的是为了简化基础表单开发,或方便个人demo编写
FormPro组件
index.tsx
import React, { useCallback } from 'react';
import { Form, FormProps, FormInstance } from 'antd';
import { IType, ItemType, renderItem } from './const';
interface IProps {
form: FormInstance;
items: ItemType[];
formProps?: FormProps;
}
export default function FormPro(props: IProps) {
const { items, formProps = {} } = props;
const [form] = Form.useForm();
// Form.Item 校验配置
const getRules = useCallback((rules, required: boolean) => {
if (Array.isArray(rules) && rules?.length) {
return rules;
}
if (required) {
return [{ required: true, message: '请输入' }];
}
return [];
}, []);
return (
<Form labelCol={{ span: 3 }} {...formProps} form={form}>
{items?.map((item) => {
if (!!item?.isHidden || !Object.keys(item)?.length) {
return null;
}
// 自定义渲染表单
if (item?.render) {
return item.render();
}
const rules = getRules(item?.formItemProps?.rules, !!item?.required);
const inputProps = {
options: item?.options ?? [],
...(item?.inputProps ?? {}),
};
const children = renderItem(item?.type as IType, inputProps);
return (
<Form.Item key={item.name} label={item.label} name={item.name} rules={rules} {...(item?.formItemProps ?? {})}>
{children}
</Form.Item>
);
})}
</Form>
);
}
const.tsx
import {
DatePicker,
DatePickerProps,
Input,
InputNumber,
InputNumberProps,
InputProps,
Radio,
RadioGroupProps,
Select,
SelectProps,
TimePickerProps,
Checkbox,
FormItemProps,
} from 'antd';
import { CheckboxGroupProps } from 'antd/es/checkbox';
import { RangePickerProps } from 'antd/es/date-picker';
import { TextAreaProps } from 'antd/es/input';
interface IOptions {
label: string;
value: any;
}
export type IType =
| 'Input'
| 'TextArea'
| 'InputNumber'
| 'Select'
| 'DatePicker'
| 'TimePicker'
| 'RangePicker'
| 'RadioGroup'
| 'CheckboxGroup';
type PropsMap = {
Input: InputProps;
TextArea: TextAreaProps;
InputNumber: InputNumberProps;
Select: SelectProps;
DatePicker: DatePickerProps;
TimePicker: TimePickerProps;
RangePicker: RangePickerProps;
RadioGroup: RadioGroupProps;
CheckboxGroup: CheckboxGroupProps;
};
export interface ItemType<T extends IType = IType> {
label?: string;
name?: string;
type?: T;
/** 优先级更高 */
formItemProps?: FormItemProps;
required?: boolean;
/** 优先级更高 */
inputProps?: PropsMap[T];
options?: IOptions[];
/** 配置自定义组件时,label和name只有字段描述作用 */
render?: () => React.ReactNode;
/** 展示false/隐藏true */
isHidden?: boolean;
}
export const renderItem = (type: IType, props) => {
switch (type) {
case 'Input':
return <Input placeholder="请输入" {...props} />;
case 'TextArea':
return <Input.TextArea placeholder="请输入" {...props} />;
case 'InputNumber':
return <InputNumber placeholder="请输入" controls={false} {...props} />;
case 'Select':
return <Select placeholder="请选择" {...props} />;
case 'DatePicker':
return <DatePicker {...props} />;
case 'TimePicker':
return <DatePicker.TimePicker {...props} />;
case 'RangePicker':
return <DatePicker.RangePicker {...props} />;
case 'RadioGroup':
return <Radio.Group {...props} />;
case 'CheckboxGroup':
return <Checkbox.Group {...props} />;
default:
return <Input placeholder="请输入" {...props} />;
}
};