美文网首页基础前端
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