文章系列
上一章:# 如何从0到1搭建基于antd的monorepo库------子包初始化(二)
作者有话说
目前已经实现了一部分功能,源代码在 github,欢迎大家 Star 和 PR,一些待实现的功能都在 issue 中,感兴趣的同学可以一起加入进来。
看完这个系列可以收获什么:
- 如何使用 pnpm workspace + lerna 搭建 monorepo 仓库
- antd 的单个组件怎么进行文件结构的设计
- 基于 antd form 实现一个 Json 渲染表单
- antd 的打包方式以及如何使用 rollup 实现
- 如何发布 monorepo 包到 npm
前瞻
组件库技术选型:
- pnpm 10
- node 20
- lerna 8
- react 18
- antd 5
- dumi 2
正片开始
搭建组件目录结构
进入 packages/basic
子包。
在 src
下新增 JsonSchemaForm
文件夹,以及 JsonSchemaForm/index.ts
、JsonSchemaForm/JsonSchemaForm.tsx
、JsonSchemaForm/JsonSchemaFormItem.tsx
、JsonSchemaForm/constants.ts
、JsonSchemaForm/type.ts
文件。
bash
- JsonSchemaForm
- index.ts # 对外的窗口
- JsonSchemaForm.tsx # 组件入口
- JsonSchemaFormItem.tsx # 子组件
- type.ts # 类型文件
- constants.ts # 常量文件
初始化组件
文章中组件是一步一步设计的,可能会导致代码比较分散,如果想看完整代码可以直接去 github。
在 JsonSchemaForm/JsonSchemaForm.tsx
中新增代码。
tsx
import { Button, Form, Space } from 'antd';
import JsonSchemaFormItem from './JsonSchemaFormItem';
import { JsonSchemaFormProps } from './type';
const JsonSchemaForm = ({ schema, formProps }: JsonSchemaFormProps) => {
const [form] = Form.useForm();
return (
<Form scrollToFirstError layout="vertical" {...formProps} form={form}>
{schema.map((item) => (
<JsonSchemaFormItem key={item.formItemProps.name} {...item} />
))}
<Form.Item>
<Space>
<Button type="primary" htmlType="submit">
提交
</Button>
<Button onClick={() => form.resetFields()}>重置</Button>
</Space>
</Form.Item>
</Form>
);
};
export default JsonSchemaForm;
在 JsonSchemaFormItem.tsx
中新增代码。
tsx
import { Form } from 'antd';
import React from 'react';
import { RENDER_MAP } from './constants';
const JsonSchemaFormItem = ({ $type, formItemProps, ...componentProps }) => {
return (
<Form.Item key={formItemProps.name} {...formItemProps}>
{React.createElement(RENDER_MAP[$type], {
...componentProps,
})}
</Form.Item>
);
};
export default JsonSchemaFormItem;
在 JsonSchemaForm/constants.ts
中新增代码。
ts
import {
Cascader,
Checkbox,
ColorPicker,
DatePicker,
Input,
InputNumber,
Mentions,
Radio,
Rate,
Segmented,
Select,
Slider,
Switch,
TimePicker,
TreeSelect,
Upload,
} from 'antd';
import type { ComponentType } from 'react';
import JsonSchemaAutoComplete from './components/JsonSchemaAutoComplete';
import { JsonSchemaFormItemTypeType } from './type';
export const RENDER_MAP: Record<
JsonSchemaFormItemTypeType,
ComponentType<any>
> = {
// input
input: Input,
password: Input.Password,
search: Input.Search,
textarea: Input.TextArea,
opt: Input.OTP,
inputNumber: InputNumber,
mentions: Mentions,
autoComplete: JsonSchemaAutoComplete,
// select
select: Select,
treeSelect: TreeSelect,
cascader: Cascader,
// check
radio: Radio.Group,
checkbox: Checkbox.Group,
segmented: Segmented,
rate: Rate,
slider: Slider,
switch: Switch,
// picker
datePicker: DatePicker,
rangePicker: DatePicker.RangePicker,
timePicker: TimePicker,
colorPicker: ColorPicker,
// upload
upload: Upload,
dragger: Upload.Dragger,
};
在 JsonSchemaForm/type.ts
中新增代码。
ts
import {
AutoCompleteProps,
CascaderProps,
ColorPickerProps,
DatePickerProps,
DraggerProps,
FormItemProps,
FormProps,
InputNumberProps,
InputProps,
MentionsProps,
RadioGroupProps,
RateProps,
SegmentedProps,
SelectProps,
SwitchProps,
TimePickerProps,
TreeSelectProps,
UploadProps,
} from 'antd';
import { CheckboxGroupProps } from 'antd/es/checkbox';
import { RangePickerProps } from 'antd/es/date-picker';
import { PasswordProps, SearchProps, TextAreaProps } from 'antd/es/input';
import { OTPProps } from 'antd/es/input/OTP';
import { SliderProps } from 'antd/es/slider';
import { Dispatch, SetStateAction } from 'react';
export type JsonSchemaFormItemTypeType =
// input
| 'input'
| 'password'
| 'search'
| 'textarea'
| 'opt'
| 'inputNumber'
| 'mentions'
| 'autoComplete'
// select
| 'select'
| 'treeSelect'
| 'cascader'
// check
| 'radio'
| 'slider'
| 'checkbox'
| 'segmented'
| 'switch'
// picker
| 'rate'
| 'datePicker'
| 'rangePicker'
| 'timePicker'
| 'colorPicker'
// upload
| 'upload'
| 'dragger';
export type filterCustomProps<T> = Omit<T, 'onChange'>;
// 基础接口,包含所有表单项共有的属性
interface BaseJsonSchemaFormItem {
formItemProps: FormItemProps;
onChange?: (
value: any,
[formProps, setFormProps]: [FormProps, Dispatch<SetStateAction<FormProps>>],
) => void;
}
interface InputJsonSchemaFormItem
extends filterCustomProps<InputProps>,
BaseJsonSchemaFormItem {
$type: 'input';
}
interface InputPasswordJsonSchemaFormItem
extends filterCustomProps<PasswordProps>,
BaseJsonSchemaFormItem {
$type: 'password';
}
interface InputNumberJsonSchemaFormItem
extends filterCustomProps<InputNumberProps>,
BaseJsonSchemaFormItem {
$type: 'inputNumber';
}
interface TextareaJsonSchemaFormItem
extends filterCustomProps<TextAreaProps>,
BaseJsonSchemaFormItem {
$type: 'textarea';
}
interface SearchJsonSchemaFormItem
extends filterCustomProps<SearchProps>,
BaseJsonSchemaFormItem {
$type: 'search';
}
export interface AutoCompleteJsonSchemaFormItem
extends Omit<filterCustomProps<AutoCompleteProps>, 'onSearch'>,
BaseJsonSchemaFormItem {
$type: 'autoComplete';
onSearch?: (
value: string,
[options, setOptions]: [
AutoCompleteProps['options'],
Dispatch<SetStateAction<AutoCompleteProps['options']>>,
],
) => void;
}
interface SelectJsonSchemaFormItem
extends filterCustomProps<SelectProps>,
BaseJsonSchemaFormItem {
$type: 'select';
}
interface TreeSelectJsonSchemaFormItem
extends filterCustomProps<TreeSelectProps>,
BaseJsonSchemaFormItem {
$type: 'treeSelect';
}
interface OptJsonSchemaFormItem
extends filterCustomProps<OTPProps>,
BaseJsonSchemaFormItem {
$type: 'opt';
}
interface RadioJsonSchemaFormItem
extends filterCustomProps<RadioGroupProps>,
BaseJsonSchemaFormItem {
$type: 'radio';
}
interface CheckboxJsonSchemaFormItem
extends filterCustomProps<CheckboxGroupProps>,
BaseJsonSchemaFormItem {
$type: 'checkbox';
}
interface CascaderJsonSchemaFormItem
extends filterCustomProps<CascaderProps>,
BaseJsonSchemaFormItem {
$type: 'cascader';
}
interface SegmentedJsonSchemaFormItem
extends filterCustomProps<SegmentedProps>,
BaseJsonSchemaFormItem {
$type: 'segmented';
}
interface DatePickerJsonSchemaFormItem
extends filterCustomProps<DatePickerProps>,
BaseJsonSchemaFormItem {
$type: 'datePicker';
}
interface RangePickerJsonSchemaFormItem
extends filterCustomProps<RangePickerProps>,
BaseJsonSchemaFormItem {
$type: 'rangePicker';
}
interface TimePickerJsonSchemaFormItem
extends filterCustomProps<TimePickerProps>,
BaseJsonSchemaFormItem {
$type: 'timePicker';
}
interface ColorPickerJsonSchemaFormItem
extends filterCustomProps<ColorPickerProps>,
BaseJsonSchemaFormItem {
$type: 'colorPicker';
}
interface MentionsJsonSchemaFormItem
extends filterCustomProps<MentionsProps>,
BaseJsonSchemaFormItem {
$type: 'mentions';
}
interface RateJsonSchemaFormItem
extends filterCustomProps<RateProps>,
BaseJsonSchemaFormItem {
$type: 'rate';
}
interface SliderJsonSchemaFormItem
extends filterCustomProps<SliderProps>,
BaseJsonSchemaFormItem {
$type: 'slider';
}
interface SwitchJsonSchemaFormItem
extends filterCustomProps<SwitchProps>,
BaseJsonSchemaFormItem {
$type: 'switch';
}
interface UploadJsonSchemaFormItem
extends filterCustomProps<UploadProps>,
BaseJsonSchemaFormItem {
$type: 'upload';
}
interface DraggerJsonSchemaFormItem
extends filterCustomProps<DraggerProps>,
BaseJsonSchemaFormItem {
$type: 'dragger';
}
export type JsonSchemaFormItemType =
// input
| InputJsonSchemaFormItem
| InputPasswordJsonSchemaFormItem
| TextareaJsonSchemaFormItem
| SearchJsonSchemaFormItem
| OptJsonSchemaFormItem
| InputNumberJsonSchemaFormItem
| MentionsJsonSchemaFormItem
| AutoCompleteJsonSchemaFormItem
// select
| SelectJsonSchemaFormItem
| TreeSelectJsonSchemaFormItem
| CascaderJsonSchemaFormItem
// check
| RadioJsonSchemaFormItem
| CheckboxJsonSchemaFormItem
| SegmentedJsonSchemaFormItem
| RateJsonSchemaFormItem
| SliderJsonSchemaFormItem
| SwitchJsonSchemaFormItem
// picker
| DatePickerJsonSchemaFormItem
| RangePickerJsonSchemaFormItem
| TimePickerJsonSchemaFormItem
| ColorPickerJsonSchemaFormItem
// upload
| UploadJsonSchemaFormItem
| DraggerJsonSchemaFormItem;
export interface JsonSchemaFormProps {
schema: JsonSchemaFormItemType[];
formProps?: FormProps;
}
最后,在 JsonSchemaForm/index.ts
中对外暴露组件以及 ts 类型。
ts
import JsonSchemaForm from './JsonSchemaForm';
export type { JsonSchemaFormItemType } from './type';
export default JsonSchemaForm;
在子包统一入口暴露组件以及 ts 类型
在 src/index.ts
中新增代码。
ts
export { default as JsonSchemaForm } from './JsonSchemaForm';
export type { JsonSchemaFormItemType } from './JsonSchemaForm';
总结
至此,一个适配 antd 几乎所有内置组件的 Json 渲染表单已经完成,但是,在实际应用场景中 antd 内置的组件往往不够用,所以需要提供一个自定义的入口来让用户渲染自己想要的组件。
接下来,我们将会对 JsonSchemaForm 组件进行优化。
如果想提前知道更多内容可以直接查看github,欢迎大家 Star 和 PR,如有疑问可以评论或私信。