Vue+Async-Validatorls表单验证

1,134 阅读2分钟

先上效果图

image.png

实现功能

  • 必填项校验,鼠标失去焦点时提示 “不可以为空”
  • 特殊校验如手机号,鼠标失去焦点时根据相应校验规则提示相应信息
  • 用户提交表单前需勾选☑️已阅读
  • 提交表单时 ,统一校验,根据规则提示相应信息

实现原理

Async-Validator 是一个表单异步校验库,这里我们通过这个库来实现一个完整的表单校验

代码实现

安装Async-Validator 依赖

npm install async-validator

表单代码

先准备基本的表单结构并完成v-model绑定

<template>
    <div>
        <form action="">
            <div>
                <div>
                    <div>
                        <span>*</span>
                        <span>姓名</span>
                    </div>
                    <input v-model="formData.name" type="text" placeholder="请输入姓名" />
                </div>
                <div>
                    <div>
                        <span>*</span>
                        <span>年龄</span>
                    </div>
                    <input v-model="formData.age" type="text" placeholder="请输入年龄" />
                </div>
                <div>
                    <div>
                        <span>*</span>
                        <span>手机号</span>
                    </div>
                    <input v-model="formData.phone" type="text" placeholder="请输入手机号" />
                </div>
            </div>
            <div>
                <img
                    :src="
                        formData.confirm
                            ? 'https://p0.ssl.qhimg.com/t010b61cc9df1ab4164.png'
                            : 'https://p4.ssl.qhimg.com/t01ab1de47e94269c76.png'
                    "
                    alt=""
                />
                <span>请确认已阅读并同意</span>
                <a>《用户协议和隐私》</a>
            </div>
            <div @click="submit">提交</div>
        </form>
    </div>
</template>

<script>
export default {
    data(){
      return {
        formData: {
              name: null,
              age: null,
              phone: null,
              confirm: false
          }
      }
  }
}
</script>

现在一个表单的基本结构已经完成,样式比较简单这里就不展示代码了(最后会给出所有代码)

添加表单校验

  1. 引入async-validator
  2. 根据表单校验规则定义一个对象rules,对象内包含校验规则和校验不通过的信息提示,每个对象都可以配置多条校验规则,也可以自定义校验规则
  3. 实例化 Schema, 将 rules 传入 Schema,得到一个 validator
//script
<script>
  import Schema from 'async-validator';
  export default {
    data(){
      return {
         rules: {
                name: [
                    {
                        required: true,
                        message: '姓名不可以为空'
                    },
                  {
                        required: true,
                        message: '最多输入100字',
                        max: 100
                    }
                ],
                age: [
                    {
                        required: true,
                        message: '年龄不可以为空'
                    },
                    {
                        required: true,
                        pattern: /^([1-9]\d?|1[01]\d|120)$/,
                        message: '请输入数字'
                    }
                ],
                phone: [
                    {
                        required: true,
                        message: '手机号不可以为空'
                    },
                    {
                        required: true,
                        pattern:
                            /^(13[0-9]|14[01456879]|15[0-35-9]|16[2567]|17[0-8]|18[0-9]|19[0-35-9])\d{8}$/,
                        message: '请输入正确手机号'
                    }
                ],
                confirm: [
                        {
                            required: true,
                            message: '请确认已阅读并同意'
                        }
                 ]
            }
      }
    }
    created() {
        this.validator = new Schema(this.rules);
    },
        
  }
</script>
  1. 验证单个表单

给name,age,phone 分别添加失去焦点事件@blur,给confirm添加点击事件@click

<template>
    <div>
        <form action="">
            <div>
                <div>
                    <div>
                        <span>*</span>
                        <span>姓名</span>
                    </div>
                    <input v-model="formData.name" type="text" placeholder="请输入姓名" @blur="handleBlurName"/>
                </div>
                <div>
                    <div>
                        <span>*</span>
                        <span>年龄</span>
                    </div>
                    <input v-model="formData.age" type="text" placeholder="请输入年龄" @blur="handleBlurAge"/>
                </div>
                <div>
                    <div>
                        <span>*</span>
                        <span>手机号</span>
                    </div>
                    <input v-model="formData.phone" type="text" placeholder="请输入手机号" @blur="handleBlurPhone"/>
                </div>
                <div>
                  <img
                      :src="
                          formData.confirm
                              ? 'https://p0.ssl.qhimg.com/t010b61cc9df1ab4164.png'
                              : 'https://p4.ssl.qhimg.com/t01ab1de47e94269c76.png'
                      "
                      alt=""
                      @click="clickConfirm"
                  />
                  <span>请确认已阅读并同意</span>
                  <a>《用户协议和隐私》</a>
                </div>
            </div>
            <div @click="submit">提交</div>
        </form>
    </div>
</template>

将实例化后的校验器函数写到 失去blur函数(handleBlurName,handleBlurAge,handleBlurPhone)和click函数(clickConfirm)

handleBlurName() {
    this.validator.validate({ name: this.formData.name }, (errors, fields) => {
        if (errors && fields.name) {
            console.log(fields.name[0].message);
            return errors;
        }
    });
},
handleBlurAge() {
    this.validator.validate({ age: this.formData.age }, (errors, fields) => {
        if (errors && fields.age) {
            console.log(fields.age[0].message);
            return errors;
        }
    });
},
handleBlurPhone() {
    this.validator.validate({ phone: this.formData.phone }, (errors, fields) => {
        if (errors && fields.phone) {
            console.log(fields.phone[0].message);
            return errors;
        }
    });
},
clickConfirm() {
    this.formData.confirm = !this.formData.confirm;
    this.validator.validate({ confirm: this.formData.confirm }, (errors, fields) => {
        if (errors && fields.confirm) {
            return errors;
        }
    });
},

测试一下,控制台打印出姓名不可以为空,此时我们单个表单的校验就已经完成了

5、多个表单校验

在提交按钮定义一个点击事件为submit,记得阻止浏览器默认事件

submit(e) {
    e.preventDefault();
    this.validator
        .validate(this.formData)
        .then(() => {
            console.log('验证通过');
        })
        .catch(({ errors, fields }) => {
            console.log('校验不通过');
            for (let key in fields) {
              console.log(key,errors);
            }
            return errors;
        });
}

👇验证一下效果

不符合校验规则,点击提交,验证不通过

符合验证规则,点击提交,控制台显示验证通过

现在一个基本的表单功能已经实现了

完善提示功能

先定义一个对象modelControl,用来动态存储错误信息

 modelControl: {},

添加错误信息和input红色边框的显示和隐藏,同时给input添加自定义属性 prop

<input
    v-model="formData.name"
    type="text"
    placeholder="请输入姓名"
    @blur="handleBlurName"
    prop="name"
    :class="{ borderColor: modelControl['name'] }"
/>
<div class="text-xs text-red1 ml-13px">
    {{ modelControl['name'] }}
</div>

.borderColor{
    border: 1px solid red;
}

修改失去焦点事件和点击事件来动态显示和隐藏提示

handleBlurName(e) {
  const prop = e.target.attributes.prop.value;
  if (!prop) {
    return false;
  }
  this.validator.validate({ name: this.formData.name }, (errors, fields) => {
    if (errors && fields.name) {
      this.$set(this.modelControl, prop, fields[prop][0].message);
      return errors;
    }
    this.$set(this.modelControl, prop, null);
  });
},
submit(e) {
    e.preventDefault();
    this.validator
        .validate(this.formData)
        .then(() => {
            console.log('验证通过');
        })
        .catch(({ errors, fields }) => {
            console.log('校验不通过');
            for (let key in fields) {
                this.$set(this.modelControl, key, fields[key][0].message);
            }
            return errors;
        });
}