React中使用async-validator进行表单验证

react中进行表单验证毫无疑问是繁琐的,尤其对于动态添加或删除的表单,其验证逻辑更为复杂, 目前UI框架使用material ui ,但其表单处理不太理想,而后研究了一下另一个UI 框架 ant design, 其对表单的处理大大方便了逻辑的编写, 它使用async-validator处理验证逻辑

目前更换框架毫无疑问是不现实的,于是就想直接引入async-validator,下面描述一个简单的使用,具体信息可以去github上查看

validate.js

import Schema from 'async-validator';

/*
* @params form: {
*   descriptor: 验证规则
*   source: 待验证字段
*   callback: 异步验证回调函数
* }
*
* @return errInfo {
*   isAllValid: 验证是否通过
 *  errors: 验证失败的字段信息
* }
* 不管验证结果成功还是失败,都会将结果信息写入errors中,方便调用者直接通过数组下标方式获取验证结果信息
* */
function validate (form) {
    let errInfo = {};
    let errStatus = [];
    let descriptor = form.descriptor;
    let validator = new Schema(descriptor);
    validator.validate(form.source, {
        firstFields: true  // 如果一个字段对应多个验证规则, 只显示验证失败的第一个规则信息,并不再进行后续规则的验证
    }, (errors, fields) => {
        if (errors) {
            /* 如需异步验证需要传入回调函数callback */
            errors.forEach(item => {
                errStatus.push(item.message.errStatus);
            });
            errInfo.errors = errors;
            errInfo.isAllValid = !errStatus.includes(true);
            form.callback && form.callback(errInfo);
        }
    });
    return errInfo;
}

export default validate;

Form.js

/**
 * Created by wxw on 18-4-26.
 */
import React from 'react';
import {inject} from 'mobx-react';
import { withStyles } from 'material-ui/styles';
import validate from '../utils/validate';
import {formTest2} from '../utils/validateRules';

import Input, { InputLabel } from 'material-ui/Input';
import { FormControl, FormHelperText } from 'material-ui/Form';
import { MenuItem } from 'material-ui/Menu';
import Select from 'material-ui/Select';
import Button from 'material-ui/Button';


const styles = theme => ({
    container: {
        display: 'flex',
        flexWrap: 'wrap',
    },
    formControl: {
        margin: theme.spacing.unit,
    },
    button: {
        margin: theme.spacing.unit,
        color: '#fff'
    },
});

@inject('rootStore')
@withStyles(styles)
class FormTest2 extends React.Component {
    state = {
        name: {
            value: '',
            errStatus: false,
            errMsg: '请输入name'
        },
        age: {
            value: '',
            errStatus: false,
            errMsg: '请选择age'
        }
    };

    handleChange =(field) => event => {
        if (field === 'name') {
            this.setState({ name: Object.assign(this.state.name, {value: event.target.value}) });
        } else if (field === 'age') {
            this.setState({ age: Object.assign(this.state.age, {value: event.target.value}) });
        }
    };

    handleCheck = (field) => () => {
        if (field === 'name') {
            let errInfo = validate({
                descriptor: formTest2,
                source: {
                    name: this.state.name.value,
                }
            });
            this.setState({ name: errInfo.errors[0].message});
        } else if (field === 'age') {
            let errInfo = validate({
                descriptor: formTest2,
                source: {
                    age: this.state.age.value,
                }
            });
            this.setState({ age: errInfo.errors[1].message });
        }
    };

    handleSubmit = () => {
        let {name, age} = this.state;
        let errInfo = validate({
            descriptor: formTest2,
            source: {
                name: name.value,
                age: age.value
            }
        });
        errInfo.errors.forEach(item => {
            this.setState({
                [item.field]: item.message
            });
        });
        if (errInfo.isAllValid) {
            console.log('验证成功');
        } else {
            console.log('验证失败');
        }
    };

    render () {
        const { classes } = this.props;
        const {name, age} = this.state;
        return (
            <div className="form2">
                <FormControl className={classes.formControl} error={name.errStatus}>
                    <InputLabel htmlFor="name-simple">Name</InputLabel>
                    <Input id="name-simple" value={name.value} onChange={this.handleChange('name')} placeholder="placeholder" onBlur={this.handleCheck('name')} />
                    <FormHelperText id="name-simple">{name.errMsg}</FormHelperText>
                </FormControl>
                <FormControl className={classes.formControl} error={age.errStatus}>
                    <InputLabel htmlFor="age-simple">Age</InputLabel>
                    <Select
                        value={age.value}
                        onChange={this.handleChange('age')}
                        onBlur={this.handleCheck('age')}
                        inputProps={{
                            name: 'age',
                            id: 'age-simple',
                        }}
                    >
                        <MenuItem value={10}>Ten</MenuItem>
                        <MenuItem value={20}>Twenty</MenuItem>
                        <MenuItem value={30}>Thirty</MenuItem>
                    </Select>
                    <FormHelperText id="age-simple">{age.errMsg}</FormHelperText>
                </FormControl>
                <Button variant="raised" color="primary" className={classes.button} onClick={this.handleSubmit}>
                    提交
                </Button>
            </div>
        )
    }
}

export default FormTest2;

validateRules.js

/**
 * Created by wxw on 18-4-26.
 */
export const formTest2 = {
    name: {
        validator(rule, value, callback, source, options) {
            /* callback必须执行一次,带参数为错误信息,不带参数为正确 */
            if (value) {
                callback({
                    errMsg: "请输入name",
                    value,
                    errStatus: false
                });
            } else {
                callback({
                    errMsg: "name不能为空",
                    value,
                    errStatus: true
                });
            }
        }
    },
    age: {
        validator(rule, value, callback, source, options) {
            /* callback必须执行一次,带参数为错误信息,不带参数为正确 */
            if (value) {
                callback({
                    errMsg: "请选择age",
                    value,
                    errStatus: false
                });
            } else {
                callback({
                    errMsg: "必选项",
                    value,
                    errStatus: true
                });
            }
        }
    },
};

综上为一个小demo,在此基础上可以进行更深层次的封装以便使用

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值