547 字
3 分钟
封装Antd表单组件
import React, { Component } from 'react'import {UserOutlined,LockOutlined} from '@ant-design/icons';
// 高阶组件const MFormCreate = Comp => { return class extends Component { constructor(props) { super(props) this.options = {} // 各个字段的选项值 它的变化不会触发组件重新渲染 this.state = {} // 各个字段的值 } // 处理表单项输入事件 handleChange = (e) => { const { name, value } = e.target this.setState({ [name]: value }, () => { // 校验 this.validateField(name) }) } // 表单项的校验 validateField = (fieldName) => { const { rules } = this.options[fieldName]
const ret = rules.some(rule => { if (rule.required) { // 输入为空 要显示错误信息 if (!this.state[fieldName]) { this.setState({ [fieldName + 'Message']: rule.message }) return true // 校验失败 } } }) if (!ret) { this.setState({ [fieldName + 'Message']: '' }) } return !ret } handleFocus = e => { const fieldName = e.target.name this.setState({ [fieldName + 'Focus']: true }) } getFieldDecorator = (fieldName, option) => { // 设置字段选项配置 this.options[fieldName] = option // 返回包装处理后的Input组件 return (InputComp) => { return <div> { // 克隆一份并添加需要的属性 React.cloneElement(InputComp, { name: fieldName, value: this.state[fieldName] || '', onChange: this.handleChange, onFocus: this.handleFocus }) } </div> } } // 验证全部表单项 validateFields = (cb) => { const rets = Object.keys(this.options).map(fieldName => this.validateField(fieldName)) const ret = rets.every(v => v === true) cb(ret) } // 判断控件是否被点击过 isFieldTouched = fieldName => !!this.state[fieldName + 'Focus'] // 获取控件的错误信息 getFieldError = fieldName => this.state[fieldName + 'Message'] // 表单相关API form = () => { return { getFieldDecorator: this.getFieldDecorator, validateFields: this.validateFields, isFieldTouched: this.isFieldTouched, getFieldError: this.getFieldError } } render() { return ( <div> <Comp {...this.props} form={this.form()}></Comp> </div> ); } }
}class FormItem extends Component { render() { return ( <div> {this.props.children} {/* 错误信息展示 */} { this.props.validateStatus && ( <p style={{ color: 'red' }}>{this.props.help}</p> ) } </div> ); }}// 对input的扩展class Input extends Component { render() { return ( <div> {this.props.prefix} <input type="text" {...this.props}/> </div> ); }}
class MForm extends Component { // 处理submit点击事件 handleSubmit = () => { this.props.form.validateFields(isValid => { if (isValid) { alert('校验成功!') } else { alert('校验失败,重新输入!') } }) } render() { const { getFieldDecorator, isFieldTouched, getFieldError } = this.props.form const usernameError = isFieldTouched('username') && getFieldError('username') const passwordError = isFieldTouched('password') && getFieldError('password') return ( <div> <FormItem validateStatus={usernameError ? 'error' : ''} help={usernameError || ''}> { getFieldDecorator('username', { rules: [ { required: true, message: '请填写用户名!' } ] })(<Input prefix={<UserOutlined />} type="text"></Input>) } </FormItem> <FormItem validateStatus={passwordError ? 'error' : ''} help={passwordError || ''}> { getFieldDecorator('password', { rules: [ { required: true, message: '请填写密码!' } ] })(<Input prefix={<LockOutlined />} type="password"></Input>) } </FormItem>
<input type="button" value="登录" onClick={this.handleSubmit} /> </div> ) }}export default MFormCreate(MForm)