美文网首页基础前端
antd 分步条和有验证的表单

antd 分步条和有验证的表单

作者: CondorHero | 来源:发表于2019-08-21 23:14 被阅读3次
    一、antd Steps 步骤条基本使用:

    基本代码实例:

    import React, { Component } from 'react'
    import { Steps } from 'antd';
    
    const { Step } = Steps;
    export default class S1 extends Component {
        render() {
            return (
                <div>
                    <Steps current = {0}>
                        <Step title="第一步" description="步骤的详情描述,可选"/>
                        <Step title="第二步" status = "error"/>
                        <Step title="第三步" />
                    </Steps>
                </div>
            )
        }
    }
    

    分步效果:


    二、分步条制作对应的分页

    每一步对应一个分页,应该采用信号量控制组件的形式核心代码是下面的 IIFE:

    {
        (()=>{
            if(current === 0){
                return <S1 />
            }else if(current === 1){
                return <S2 />
            }else if(current === 2){
                return <S3 />
            }else if(current === 3){
                return <S4 />
            }
        })()
    }
    

    完整代码:

    import { Steps, Button, message } from 'antd';
    
    const { Step } = Steps;
    import React, { Component } from 'react'
    import S1 from "./S1";
    import S2 from "./S2";
    import S3 from "./S3";
    import S4 from "./S4";
    export default class S extends Component {
        constructor(){
            super();
            this.state = {
                current: 0
            };
        }
        next() {
            const current = this.state.current + 1;
            this.setState({ current });
        }
    
        prev() {
            const current = this.state.current - 1;
            this.setState({ current });
        }
        render() {
            const { current } = this.state;
            return (
                <div>
                    <Steps current={current}>
                        <Step title="个人信息填写" />
                        <Step title="车辆信息" />
                        <Step title="照片上传" />
                        <Step title="成功" />
                    </Steps>
                    <div className="steps-content">
                        {
                            (()=>{
                                if(current === 0){
                                    return <S1 />
                                }else if(current === 1){
                                    return <S2 />
                                }else if(current === 2){
                                    return <S3 />
                                }else if(current === 3){
                                    return <S4 />
                                }
                            })()
                        }
                    </div>
                    <div className="steps-action">
                        {current < 3 && (
                        <Button type="primary" onClick={() => this.next()}>
                        下一步
                        </Button>
                        )}
                        {current >= 3 && (
                        <Button type="primary" onClick={() => message.success('已完成提交,请稍后!')}>
                        提交
                        </Button>
                        )}
                        {current > 0 && (
                        <Button style={{ marginLeft: 8 }} onClick={() => this.prev()}>
                        上一步
                        </Button>
                        )}
                    </div>
                </div>
            )
        }
    }
    
    测试效果
    五、Form 表单
    • 表单装饰
      官网案例:
    class CustomizedForm extends React.Component {}
    
    CustomizedForm = Form.create({})(CustomizedForm);
    

    很明显 Form.create()()十个装饰器。如果项目装个插件:@babel/plugin-proposal-decorators 就可以使用语法糖来代替上面的写法成@Form.create()

    • 表单校验
      经 Form.create() 包装过的组件会自带 this.props.form 属性
    const { getFieldDecorator } = this.props.form;
    

    getFieldDecorator 用于和表单进行双向绑定,可以定义此表单是否是必填项,前面会加一个星号表示必填,还能校验输入是否正确。

    import React, { Component } from 'react'
    import { Form , Input , Col,Row} from 'antd';
    @Form.create(
        { name: '第一个表单' }
    )
    export default class S1 extends Component {
        render() {
            // getFieldDecorator校验填写是否正确
            const { getFieldDecorator} = this.props.form;
            // <Form.Item {...formItemLayout} label="E-mail">
            // 让输入框和label里面的文字在同一水平面上
            const formItemLayout = {
                //  label 标签布局,同 <Col> 组件,设置 span offset 值
                labelCol: {
                    xs: { span: 24 },
                    sm: { span: 3 }
            },
            // 需要为输入控件设置布局样式时,使用该属性,用法同 labelCol
                wrapperCol: {
                    xs: { span: 24 },
                    sm: { span: 6 },
                }
            };
            return (
                <div>
                    <Form>
                        {/* label 是标签的文本*/}
                        <Form.Item {...formItemLayout} label="E-mail">
                            {
                                getFieldDecorator('email', {
                                    rules: [
                                        {   
                                            // type定义输入的类型
                                            type: 'email',
                                            message: '逗我那,这个邮箱不能用,从新输入一个'
                                        },
                                        {   
                                            /*加星号,message忘记填的提示信息*/
                                            required: true,
                                            message: '兄弟你忘记填这项了!'
                                        }
                                    ]
                                }
                            )(<Input />)
                            }
                        </Form.Item>
                    </Form>
                </div>
            )
        }
    }
    
    实时校验.gif
    上面我们输入一直校验,这是因为options.validateTrigger 校验子节点值的时机 默认为 onChange体验不好我们在 rule 更改校验子节点值的时机,填写完成在进行校验:
    {
        getFieldDecorator('email', {
            rules: [
                {
                    // type定义输入的类型
                    type: 'email',
                    message: '逗我那,这个邮箱不能用,从新输入一个'
                },
                
                {   
                    /*加星号表示必填,message忘记填的提示信息*/
                    required: true,
                    message: '兄弟你忘记填这项了!'
                }
            ],
            validateTrigger:"onBlur"
        }
    )(<Input />)
    }
    

    rules 里面包含了校验规则:

    • require true 或 false 这个表示是否是必填,外观上看有个星
    • type 内置校验 基本和 input 的 type 相同
    • pattern 正则表达式校验可替代 type
    • message 校验文案
    • validator: 自定义校验规则。
      validator 比较难这里演示下用法,这个自定义主要是用来检测比较偏僻的验证,这里以正则举例并不是太好,因为正则完全可以替换掉它,用来演示下用法还是无碍的:
    {
    getFieldDecorator('email', {
        rules: [
            {
                validator(rule, value, callback){
                    if(!value){
                        // 什么都不输入的时候使用回调
                        // 来调用message的提示信息
                        callback();
                        return;
                    }
                    if(/^([A-Za-z0-9_\-\.])+\@([A-Za-z0-9_\-\.])+\.([A-Za-z]{2,4})$/.test(value)){
                        callback('邮箱填写正确!');
                    }else{
                        // 输入不正确提示信息
                        callback('兄弟你写的邮箱不对!');
                    }
                }
            },
            
            {   
                /*加星号表示必填,message忘记填的提示信息*/
                required: true,
                message: '兄弟你忘记填这项了!'
            }
        ]
    }
    

    测试效果很好:


    validator: 自定义校验规则

    补充:
    昨天刚演示的这个案例,虽然能通过案例来知道它的用法,但是不知道这个方法的精髓。恰好今天想到个牛叉的案例。身份证和姓名人证匹配查询案例

    后台查询的接口是在阿里买的,使用他们提供的代码,因为我只懂 PHP 和 nodeJS 所以可以从这两个中选择任意后台语言进行调试。

    使用 PHP 写好代码,直接访问代码接口进行测试:

    http://192.168.2.250:9027/check.php?idcard=321322198303183032&name=戚光明
    

    程序返回的结果:

    string(843) "HTTP/1.1 200 OK Server: Tengine Date: Thu, 22 Aug 2019 06:37:27 GMT Content-Type: application/json;charset=utf-8 Content-Length: 324 Connection: keep-alive Access-Control-Allow-Origin: * Access-Control-Allow-Methods: GET, POST, OPTIONS Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With Access-Control-Max-Age: 172800 X-Ca-Request-Id: CA906DBE-2344-4B81-AD2C-F545FDF94B74 showapi_fee_num: 1 Access-Control-Allow-Credentials: true showapi_paycut: 1 { "showapi_res_error": "", "showapi_res_id": "4f9ec9db57bc480d8ff709da1f9a3325", "showapi_res_code": 0, "showapi_res_body": {"ret_code":0,"code":0,"msg":"匹配","birthday":"1983-03-18","sex":"M","address":"江苏宿迁市沭阳县"} } "
    

    其中重要的字段是:"msg":"匹配"这就行了。

    声明:姓名身份证是上网百度找的,请不要随便使用。如有侵权,联系删除。

    然后使用 validator 。来实现下面功能。

    人证匹配检测
    源代码:正则验证输入内容,鼠标离开第二个框发送 Ajax 。获取第一个输入框的内容使用的是:
    const { getFieldValue } = this.props.form;
    validator(rule, value, callback){
        if(!value){
            // 什么都不输入的时候使用回调
            // 来调用message的提示信息
            callback();
            return;
        }
        if(/^[1-9]\d{7}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{3}$|^[1-9]\d{5}[1-9]\d{3}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{3}([0-9]|X)$/.test(value)){
            // 得到上个组件的值
            const name = getFieldValue("name");
            // 正则匹配成功发送公安部进行姓名和身份证匹配
            // 是否人证合一
            axios.get(`http://192.168.2.250:9027/check.php?idcard=${value}&name=${name}`).then(data=>{
            if(data.data.includes('"msg":"匹配"')){
                callback('姓名和身份证匹配!');
            }else{
                callback('提示你呀姓名和身份证不匹配!');
            }
        });
        }else{
            // 输入不正确提示信息
            callback('身份证信息不正确!');
        }
    }
    
    六、验证表单所有域的正确性

    有张表单需要用户填写,结果用户没写或有的没写,想直接跳到下一步,这时就得给出必要的提示。


    空表单提示.gif

    S1 组件因为经过装饰器装饰,这个组件就会平白增加很多方法和属性。其中有个方法 validateFields() 就可以检查表单是否是正确填写,这个方法有个回调函数,函数的形参 res 就是记录返回的错误,如果没错误返回的结果 null ,是 null 我们就可以进入下一页了。

    {current < 3 && (<Button type="primary" onClick={() => {
        if(current === 0){
            console.log(this.refs.s1)
            // validateFields可以检查组件是否全部验证正确
            // console.log(this.refs.s1.validateFields());直接返回一个Promise对象
            this.refs.s1.validateFields((res)=>{
                console.log(res);
                // 全部填完返回结果为null
                if(res === null){
                    // 进入下一页
                    this.next();
                }
            });
            // 
        }
    }}>下一步</Button>)}
    
    六、表单手机短信验证

    前端接收到验证码发送给后端,后台验证密码的两种常见方式:

    • session 的验证,可以使用 PHP 打开 session ,发送 http 请求的时候带着session验证。
    • token 验证 为了密码的安全使用 md5 加密,前端请求的时候,后台响应一个 md5 加密密令(token),前端发送验证码的时候拿着 token 密令和短信验证码再次请求服务器,接收服务器的响应。
      整个过程,鼠标离开第二个输入框,触发验证码匹配事件。


      验证码.gif
    <Form>
        {/* label 是标签的文本*/}
    <Form.Item {...formItemLayout} label="手机号">
        {
            getFieldDecorator('phone', {
                rules: [
                    {
                        // 正则匹配验证
                        pattern: /^[1]([3-9])[0-9]{9}$/,
                        message: '这是哪国的手机号,我怎么从没见过!'
                    },
                    {   
                        /*加星号表示必填,message忘记填的提示信息*/
                        required: true,
                        message: '兄弟你忘记填这项了!'
                    }
                ],
                validateTrigger:"onBlur"
            }
        )(<Input />)
        }
        </Form.Item>
        {/* label 是标签的文本*/}
    <Form.Item {...formItemLayout} label="验证码">
        <Row gutter={8}>
            <Col span={12}>
        {
            getFieldDecorator('VerificationCode', {
                rules: [
                    {
                        validator:(rule, value, callback)=>{
                            if(!value){
                                // 什么都不输入的时候使用回调
                                // 来调用message的提示信息
                                callback();
                                return;
                            };
                            // 验证码是四位数
                            if(/^[0-9]{4}$/.test(value)){
                                // 验证输入的验证码是否正确
                                axios.get(`http://192.168.2.250:9027/b.php?yanzhengma=${value}&token=${this.state.token}`).then(data=>{
                                    if(data.data == "ok"){
                                        callback("验证码正确!")
                                    }else{
                                        callback("验证码错误请重新发送请求!")
                                    }
                                });                                             
                            }else{
                                // 输入不正确提示信息
                                callback('验证码是0-9的四位数字');
                            }
                        }
                    },                                  
                    {   
                        /*加星号表示必填,message忘记填的提示信息*/
                        required: true,
                        message: '兄弟你忘记填这项了!'
                    }
                ],
                validateTrigger:"onBlur"
            }
        )(<Input />)
        }
            </Col>
            <Col span={12}>
                    <Button onClick = {()=>{
                        this.setState({
                            isShow : true
                        });
                        // 得到上个组件的值
                        const phone = getFieldValue("phone");
                        axios.get(`http://192.168.2.250:9027/a.php?phone=${phone}`).then(data=>{
                            this.setState({
                                token:data.data
                            })
                        });
                        this.timer = setInterval(()=>{
                            this.setState({
                                time : this.state.time - 1
                            });
                            if(this.state.time <= 0){
                                clearInterval(this.timer);
                                this.setState({
                                    isShow : false,
                                    time : 60
                                });
                            }
                        },1000);
                    }} disabled = {this.state.isShow}>
                        {
                            !this.state.isShow ?
                            "发送验证码"
                            :
                            `重新发送 ${this.state.time}`
                        }
                    </Button>
            </Col>
            </Row>
        </Form.Item>
    </Form>
    

    相关文章

      网友评论

        本文标题:antd 分步条和有验证的表单

        本文链接:https://www.haomeiwen.com/subject/ogzisctx.html