antd4.0的form用着真的舒心

1,064 阅读2分钟

「这是我参与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 时不带样式,作为纯字段控件使用,个人感觉这个属性对于复杂的嵌套表单还是很好用。

例如下图的效果:

image.png

<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>

结语

如果这篇文章帮到了你,欢迎点赞👍和关注⭐️。

文章如有错误之处,希望在评论区指正🙏🙏

欢迎关注我的微信公众号,一起交流技术,微信搜索 🔍 :「 五十年以后