簡單實現antd的表單設計

這裏用到的antd v3 版本的antd

從antd的使用入手:

class NormalLoginForm extends React.Component { 
    handleSubmit = e => { 
        e.preventDefault(); 
        this.props.form.validateFields((err, values) => { 
            if (!err) { 
                console.log("Received values of form: ", values); 
                } 
            }); 
    };
    render() { 
        const { getFieldDecorator } = this.props.form; 
        return ( 
            <Form onSubmit={this.handleSubmit} className="login-form"> 
                <Form.Item> 
                    {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> 
                    {getFieldDecorator("password", 
                    { rules: [{ required: true, message: "Please input your password!" }] })
                    (
                    <Input prefix={<Icon type="lock" style={{ color: "rgba(0,0,0,.25)" }} />} 
                            placeholder="Password"/> 
                    )}
                </Form.Item>
                <Form.Item>
                    <Button type="primary" htmlType="submit" className="login-form-button">login</Button>
                </Form.Item>
            </Form>
        )
    }
}
const WrappedNormalLoginForm = Form.create({ name: "normal_login" })( NormalLoginForm );

Form.create 幹了些什麼?

  1. getFieldDecorator: 字段裝飾器 給輸入框強化功能: name字段, 驗證規則, 這其中肯定用到了input的 onChange方法
  2. validateFields: 根據規則來驗證所有的輸入項
表單設計

擴展表單的高階組件,提供輸入控件包裝、事件處理、表單校驗等

form.create的簡單實現

function MyFormCreate(Comp) {
    return class extends React.Component {
        constructor(props) { 
            super(props); 
            this.options = {}; 
            this.state = {}; 
        }
        //處理輸入事件,輸入中進行校驗
        handleChange = e => {
            let { name, value } = e.target;
            this.setState({
                [name]: value
            }, () => {
                this.validateField(name)
            })
        }
        //驗證所有字段, 將結果傳入回調函數,且調用回調函數
        validate = (cb) => {
            let isValidated = true
            
            Object.keys(this.options).forEach(field => {
                isValidated = this.validateField(field)
            })

            cb && cb(isValidated)
        }
        //驗證單個字段
        validateField(field) {
            let flag = true,
                {rules} = this.options[field]
            rules.some(rule => {
                if(rule.required) {
                    let msg = !this.state[field] && rule.message

                    this.setState({
                        [field+'errorMsg']: msg
                    })
                    
                    flag = false
                    return false
                }
            })
            return flag
        }
        //字段裝飾器
        getFieldDec = (field, option) => {
            this.options[field] = option
            return InputComp => (
                <div>
                    {React.cloneElement(InputComp, {
                        name: field,
                        value: this.state[field] || "",
                        onChange: this.handleChange
                    })}
                    {/* 校驗信息 */}
                    {this.state[field+'errorMsg']&&(<p style={{color: 'red'}}>{this.state[field+'errorMsg']}</p>)}
                </div>
            )
        }
        //將getFieldDec和validate 掛載到新組件中
        render() {
            return (
                <div>
                    <Comp {...this.props} getFieldDec={this.getFieldDec} validate={this.validate} />
                </div>
            )
        }
    }
}

使用

@MyFormCreate
class MyFormTest extends React.Component{
    onSubmit = () => {
        this.props.validate(flag => {
            console.log(flag)
        })
    }
    render() {
        let {getFieldDec} = this.props

        return (
            <div>
                {getFieldDec('username', {
                    rules: [{required: true, message: '請輸入用戶名'}]
                })(<input type="text" />)}
                {getFieldDec('password', {
                    rules: [{required: true, message: '請輸入密碼'}]
                })(<input type="password" />)}
                <button onClick={this.onSubmit}>登錄</button>
            </div>
        )
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章