「这是我参与2022首次更文挑战的第11天,活动详情查看:2022首次更文挑战」
Hope is a good thing, maybe the best of things. And no good thing ever dies—— 《The Shawshank Redemption》
前言
在前端web开发过程中,基本上都是基于react去做开发的,而且目前用最多的 UI 框架当属Ant Design,它本身的设计体验和视觉体验还是很棒的,在社区中也占有很高的地位。这几天刚好在用 4.0 的 From 组件在做一下表单的是需求。今天,我就来聊聊自己这些天使用 Form 组件的感受。
组件 3.0 历史
在 4.0 前的版本中,如果我们要做一个 Form 表单,需要在组件中包一层 Form.create({})(CustomizedForm),然后在 CustomizedForm 组件的 Form.Item 中使用 api getFieldDecorator 用于和表单进行双向绑定,方便获取表单数据和校验。
import { Form, Icon, Input, Button } from 'antd';
function hasErrors(fieldsError) {
return Object.keys(fieldsError).some(field => fieldsError[field]);
}
class HorizontalLoginForm extends React.Component {
componentDidMount() {
// To disable submit button at the beginning.
this.props.form.validateFields();
}
handleSubmit = e => {
e.preventDefault();
this.props.form.validateFields((err, values) => {
if (!err) {
console.log('Received values of form: ', values);
}
});
};
render() {
const { getFieldDecorator, getFieldsError, getFieldError, isFieldTouched } = this.props.form;
const usernameError = isFieldTouched('username') && getFieldError('username');
const passwordError = isFieldTouched('password') && getFieldError('password');
return (
<Form layout="inline" onSubmit={this.handleSubmit}>
<Form.Item validateStatus={usernameError ? 'error' : ''} help={usernameError || ''}>
{getFieldDecorator('username', {
rules: [{ required: true, message: 'Please input your username!' }],
})(
<Input
prefix={<Icon type="user" style={{ color: 'rgba(0,0,0,.25)' }} />}
placeholder="Username"
/>,
)}
</Form.Item>
<Form.Item validateStatus={passwordError ? 'error' : ''} help={passwordError || ''}>
{getFieldDecorator('password', {
rules: [{ required: true, message: 'Please input your Password!' }],
})(
<Input
prefix={<Icon type="lock" style={{ color: 'rgba(0,0,0,.25)' }} />}
type="password"
placeholder="Password"
/>,
)}
</Form.Item>
<Form.Item>
<Button type="primary" htmlType="submit" disabled={hasErrors(getFieldsError())}>
Log in
</Button>
</Form.Item>
</Form>
);
}
}
const WrappedHorizontalLoginForm = Form.create({ name: 'horizontal_login' })(HorizontalLoginForm);
ReactDOM.render(<WrappedHorizontalLoginForm />, mountNode);
4.0 组件
在 4.0 的 Form 组件中,Form.Item 表单字段组件,用于数据双向绑定、校验、布局,用法就变得很直接了,如果对Form.Item设置 name 属性就可以用于数据绑定。使用 rules 属性直接设置校验规则,设置字段的校验逻辑。4.0 新增了 noStyle 属性,为 true 时不带样式,作为纯字段控件使用,个人感觉这个属性对于复杂的嵌套表单还是很好用。
例如下图的效果:
<Form layout="inline" form={form}>
<FormItem name="expiryType" initialValue={expiryType} label="有效期" rules={[{ required: true }]}>
<Radio.Group onChange={handleChangeExpiryDate}>
<Space direction="vertical">
<Radio value="FIXED_DAYS">
固定天数
{expiryType === 'FIXED_DAYS' && (
<Space style={{ marginLeft: 16 }}>
<span>领取后</span>
<FormItem noStyle name="dayType" initialValue={dayType} rules={[{ required: true }]}>
<Select onClick={e => e.preventDefault()} style={{ width: 90 }} onChange={handleChangeDayType}>
{options.map(ele => (
<Option key={ele.value} value={ele.value}>
{ele.label}
</Option>
))}
</Select>
</FormItem>
{dayType === 'CUSTOM' && (
<FormItem name="customDay" noStyle rules={[{ required: true, message: '请输入' }]}>
<InputNumber min={0} />
</FormItem>
)}
<span>{dayType === 'CUSTOM' ? '天' : null}生效,有效期</span>
<FormItem noStyle name="expiryDays" rules={[{ required: true, message: '请输入' }]}>
<InputNumber min={0} />
</FormItem>
<span>天</span>
</Space>
)}
</Radio>
<Radio value="FIXED_DATE">
<span style={{ marginRight: 16 }}>固定日期</span>
{expiryType === 'FIXED_DATE' && (
<FormItem
noStyle
name="fixedDate"
initialValue={[]}
rules={[{ required: true, message: '请选择日期' }]}
>
<RangePicker format={dateFormat} />
</FormItem>
)}
</Radio>
</Space>
</Radio.Group>
</FormItem>
</Form>
结语
如果这篇文章帮到了你,欢迎点赞👍和关注⭐️。
文章如有错误之处,希望在评论区指正🙏🙏
欢迎关注我的微信公众号,一起交流技术,微信搜索 🔍 :「 五十年以后 」