组件的名称统一大写,以大驼峰命名,和 Antd组件保持一致
import React, { useState, useRef } from 'react';
import PropTypes from 'prop-types';
import { Button, Drawer } from 'antd';
import { CreateSuccess } from '@constants/message'
import { FormBuild } from '@components/Form'
import { formData } from './_formData';
function App() {
function onSubmit() {
const form = formRef.current;
}
function buttonClick() {
CreateSuccess()
}
return (
<FormBuild
col={24}
dataSource={formData(buttonClick)}
ref={formRef}
onSubmit={onSubmit}
/>
)
}
FormBuild
FormBuild/index.js
import React from 'react';
import PropTypes from 'prop-types';
import classnames from 'classnames';
import { Row, Col, Form, Button, Tooltip, Icon } from 'antd';
import FormConfig from './FormConfig';
const itemLayout = {
labelCol: { span: 6 }, wrapperCol: { span: 18 },
};
FormBuild.propTypes = {
dataSource: PropTypes.array.isRequired,
onSubmit: PropTypes.func,
action: PropTypes.bool,
};
FormBuild.defaultProps = {
onSubmit: () => {},
action: false,
};
function FormBuild(props) {
const {
form, dataSource,className, action,
layout = {}, col: colWidth = 8,
} = props;
if (!dataSource.length) return null;
const { getFieldDecorator } = form;
// 表单样式
const formClass = classnames({
mb16: true,
[className]: Boolean(className)
});
// 表单布局
const formLayout = { ...itemLayout, ...layout };
const handleSubmit = (ev) => {
ev.preventDefault();
// const values = form.getFieldsValue();
form.validateFieldsAndScroll((err, values) => {
if(err) return;
onSubmit(values);
// onReset();
});
};
function onReset() {
form.resetFields();
};
return (
<Form
{...formLayout}
className={formClass}
onSubmit={handleSubmit}
>
<Row gutter={16}>
{
dataSource.map(item => {
// 解构掉不需要传递给表单组件的参数
const {
label, name, colon = true, extra, rules, col = colWidth,
valuePropName = 'value', value, noStyle, ...args
} = item;
const COMPONENT = <FormConfig {...args} />;
return (
<Col span={col} key={name}>
<Form.Item
label={label}
extra={extra}
colon={colon}
>
{
noStyle
? COMPONENT
: getFieldDecorator(name, {
initialValue: value,
rules,
valuePropName,
})(COMPONENT)
}
</Form.Item>
</Col>
);
})
}
</Row>
{
action && (
<Col span={24}>
<Button className='mr8' type='primary' htmlType='submit'>查询</Button>
<Button onClick={onReset}>重置</Button>
</Col>
)
}
</Form>
);
}
export default Form.create()(FormBuild);
label表单提示
修改 Form.Item的 label为 jsx
用不到这个功能,就不用替换,不用搞得太复杂
function LabelHelp({label, help}) {
if(!help) return label;
return (
<span>
{label}
<Tooltip title={help}>
<Icon type='question-circle-o' />
</Tooltip>
</span>
)
}
// 修改为
<Col span={col} key={name}>
<Form.Item label={<LabelHelp label={label} help={help} />}>
// ...
</Form.Item>
</Col>
Form.Item
<Form.Item
label={
<span>
Nickname
<Tooltip title="What do you want others to call you?">
<Icon type="question-circle-o" />
</Tooltip>
</span>
}
>
{getFieldDecorator('nickname', {
rules: [{ required: true, message: 'Please input your nickname!', whitespace: true }],
})(<Input />)}
</Form.Item>
FormConfig.js
FormBuild/FormConfig.js
初始化表单相关的组件,通过 props给表单添加属性
- 表单为受控组件,通过 antd的 Form,自动获取值
- value & onChange ```jsx import React from ‘react’; import { Input, InputNumber, Radio, DatePicker, Switch, AutoComplete, Button, } from ‘antd’;
import SelectArray from ‘@components/Select/SelectArray’;
const { TextArea, Password } = Input; const { RangePicker } = DatePicker;
const COMPONENT = { Input, Password, TextArea, InputNumber, Select: SelectArray, RadioGroup: Radio.Group, Switch, DatePicker, RangePicker, AutoComplete, Button, };
function FormConfig({ component, children, …props }) { const Component = COMPONENT[component]; if (!Component) return null;
return
export default FormConfig;
<a name="mJ8hY"></a>
## formData.js
```jsx
export const dataSource = [
{ label: '基金', value: 'fund' },
{ label: '黄金', value: 'gold' },
];
// 函数返回一个数组
export function formData({type, buttonClick}) {
return [
{
label: '类型',
component: 'Select',
name: 'type',
value: type,
rules: [
{ required: true, message: '请选择数据源类型' },
],
help: '必填项',
dataSource,
},
{
label: '名称',
component: 'Input',
name: 'name',
value: '',
rules: [
{ required: true, message: '请输入名称' },
],
},
{
label: '描述',
component: 'TextArea',
name: 'desc',
value: '',
extra: '描述最大长度200个字符',
},
{
label: ' ',
children: '测试配置',
component: 'Button',
type: 'dashed',
colon: false,
onClick: buttonClick,
noStyle: true,
},
{
label: '开关',
component: 'Switch',
name: 'lock',
value: true,
valuePropName: 'checked',
checkedChildren: '是',
unCheckedChildren: '否',
},
]
}
回显表单值
form.setFieldsValue
useEffect(() => {
const values = dataSource.reduce((prev, next) => {
const {name, value} = next;
prev[name] = value
return prev;
}, {});
form.setFieldsValue(values);
}, [dataSource]);