Vue form 表单异步验证终极教程 async-validator 表单校验

A kitten
知见秋
前端工程师
最近更新 2022年05月15日

Vue form 表单异步验证终极教程 async-validator 表单验证库

Vue form 表单是用户与网站 / app 重要的交互方式。而我们需要在用户提交表单前对 form 验证表单进行验证,以确保用户填写了必选项以及在本地先过滤掉错误的数据,避免这些错误数据传入,减少服务器开销,提升用户体验。

本文将手把手教你通过 Vue3 + async-validator 异步表单验证插件来完成 Vue form 表单验证功能。

async-validator 在 github 上有 8k+ 的 star, 在国内使用非常广泛,Ant.designElement UINaive UI 等都在使用这个插件,甚至与有些 Nodejs 后端项目也在使用它,特别适合国内的开发环境和应用场景。

这是最终 form 异步验证表单的完成效果

vue form finish

配置 Vue 3 开发环境及初始化项目

本教程使用的框架版本

  • Nodejs:v17.5.0
  • pnpm:7.0.0
  • Vue:3.2.25

(1)使用 Vite 配置 Vue 3

首先我们用 Vite 创建一个 Vue3 的项目demo,kalacloudFormValidate

我们在命令行输入:

pnpm create vite kalacloudFormValidate

然后选择 vue 如图

vue-setup

继续回车,结果如下图,说明我们已经初步创建了 kalacloudFormValidate (卡拉云表单验证)项目

vue-setup

根据命令行的提示,我们进入项目根目录,然后使用命令 pnpm install 安装项目需要的依赖,当然这里使用 pnpm 是比 npm 或者 yarn 快很多的。

接着,我们启动项目 pnpm run dev, 终端中输出如图内容

vue-run

启动浏览起,输入地址 http://localhost:3000/

引入表单验证插件 async-validator

这里我们使用 async-validator 表单校验插件,先安装一下,在命令行输入

pnpm install async-validator

这里 async-validator 版本是 4.1.1

到这里,Vue 3 + async-validator 表单验证插件已经全部配置完成,接着我们来看看怎么使用和实现表单验证功能。

配置表单代码

打开项目中的 App.vue 文件,删除多余的文件内容,输入标题 卡拉云 - vue3 表单验证,并添加一些初始代码

<template>
    <div class="main">
        <h2>卡拉云 - vue3 表单验证</h2>

        <form>
            <div>
                <label class="ka-la-cloud-label">账号</label>
                <input  type="text"  placeholder="请输入账号" class="ka-la-cloud-input" />
            </div>
            <div>
                <label class="ka-la-cloud-label">密码</label>
                <input  tyep="password" type="text" class="ka-la-cloud-input"  placeholder="请输入密码"  />
            </div>

            <div>
                <button>保存</button>
            </div>
        </form>
    </div>
</template>
<script setup>

</script>
<style lang="css">
.main{
    text-align:center;
}
.ka-la-cloud-label {
    padding-right: 10px;
    padding-left: 10px;
    display: inline-block;
    box-sizing: border-box;
    width: 100px;
    text-align: right;
}
.ka-la-cloud-input {
    width: 200px;
    height: 30px;
    margin-top:10px;
}
</style>

async-validator

是不是看起来有点丑,别急,我们加点 CSS 代码,简单的美化一下

<template>
    <div class="main">
        <h2>卡拉云Vue3表单验证</h2>

        <form class="form-box">
            <div class="form-group ">
                <label class="ka-la-cloud-label">账号</label>
                <input type="text" class="ka-la-cloud-input" placeholder="请输入卡拉云账号"  />
            </div>
            <div class="form-group">
                <label class="ka-la-cloud-label">密码</label>
                <input  tyep="password" type="text"  placeholder="请输入卡拉云密码" class="ka-la-cloud-input" />
            </div>

            <div class="form-group">
                <button class="btn ">保存</button>
            </div>
        </form>
    </div>
</template>
<script setup>

</script>
<style scoped>
.main {
    text-align: center;
}
.btn{
    margin: 0;
    line-height: 1;
    padding: 15px;
    height: 30px;
    width: 60px;
    font-size: 14px;
    border-radius: 4px;
    color: #fff;
    background-color: #2080f0;
    white-space: nowrap;
    outline: none;
    position: relative;
    border: none;
    display: inline-flex;
    flex-wrap: nowrap;
    flex-shrink: 0;
    align-items: center;
    justify-content: center;
    user-select: none;
    text-align: center;
    cursor: pointer;
    text-decoration: none;
}
.form-box{
    width: 500px;
    max-width: 100%;
    margin: 0 auto;
    padding: 10px;
}
.form-group{
    margin: 10px;
    padding: 10px 15px 10px 0
}
.ka-la-cloud-label {
    padding-right: 10px;
    padding-left: 10px;
    display: inline-block;
    box-sizing: border-box;
    width: 110px;
    text-align: right;
}

.ka-la-cloud-input {
    width: calc(100% - 120px);
    height: 28px;
}
</style>

添加表单验证 - 初始化

引入ref 属性和 async-validator,这里我们给每个 input 框添加 v-model 绑定属性,

// html
<input type="text" v-model="form.account" class="ka-la-cloud-input" placeholder="请输入账号"  />
<input  tyep="password" v-model="form.password" type="text"  placeholder="请输入密码" class="ka-la-cloud-input" />


// script
import { ref } from "vue"
import Schema from 'async-validator';

const form = ref({
    account: null,
    password: null,
})

根据表单的情况,我们定义一个对象,这个对象里面存储了需要校验的对象和校验不通过时的信息

const rules = {
    account: { required: true, message: '请输入账号' },
    password: { required: true, message: '请输入密码' }
}

实例化 Schema, 将 rules 传入 Schema,得到一个 validator

const validator = new Schema(rules)

验证单个表单我们使用 失去焦点事件, 定义一个函数,将这个函数添加到 account input上的失焦事件上

// html
<input v-model="account" type="text" class="ka-la-cloud-input" @blur="handleBlurAccount" placeholder="请输入账号"  />

// script
const handleBlurAccount = () => {}

接着将实例化后的校验器函数写到 handleBlurAccount 中

const handleBlurAccount = () => {
    validator.validate({account: form.value.account}, (errors, fields) => {
        if (errors && fields.account) {
            console.log(fields.account[0].message);
            return errors
        }
    })
}

在account 的 input 中测试,我们可以看到在控制台打印出了 请输入账号 等字

同样的,我们给密码框也添加如下代码

//html
<input v-model="form.password" tyep="password" type="text" @blur="handleBlurPassword"  placeholder="请输入卡拉云密码" class="ka-la-cloud-input" />

//script
const handleBlurPassword = () => {
    validator.validate({password: form.value.password}, (errors, fields) => {
        if (errors && fields.password) {
            console.log(errors, fields);
            console.log(fields.password[0].message);
            return errors
        }
    })
}

配置表单等前端问题太繁琐?

试用卡拉云,拖拽组件连接 API 和数据库直接生成后台系统,将两个月的工期降低至两天

多个表单的验证

当然这里校验的只是单个input的,我们接下来说说多个表单的校验,定义一个点击事件为submit,将submit事件添加到button上,当然不要忘记阻止浏览器默认事件

const submit = (e) => {
    e.preventDefault();
    validator.validate(form.value, (errors, fields) => {
        if (errors) {
            for(let key of errors) {
                console.log(key.message);
            }
            return errors
        }
    })

}

Promise 方式进行表单验证

了上面的方式,async-validator 还提供 Promise 的方式,我们把 submit 函数中的代码修改为如下

validator.validate(form.value).then((value) => {
        // 校验通过
        console.log(value);
}).catch(({ errors, fields }) => {
    console.log(errors);
    return errors
})

validate

点击保存,同样的,我们可以看到控制台已经打印了错误信息,说明我们写的是合适的

正则方式进行表单验证

当然有时候我们会输入邮箱,电话号码等表单,这时候我们就需要添加正则来进行验证了,我们先添加两个表单,并添加失焦事件, 正则验证需要用到 async-validator 的属性 pattern,我们将符合要求的正则添加到 rules ,代码如下所示

<div class="form-group ">
    <label class="ka-la-cloud-label">电话号码</label>
    <input v-model="form.phone" type="text" class="ka-la-cloud-input" @blur="handleBlurPhone"
                    placeholder="请输入卡拉云电话号码" />
</div>

<div class="form-group ">
    <label class="ka-la-cloud-label">邮箱</label>
    <input v-model="form.email" type="text" class="ka-la-cloud-input" @blur="handleBlurEmail"
                    placeholder="请输入卡拉云邮箱" />
</div>


const form = ref({
    account: null,
    email: null,
    password: null,
})

const rules = {
    account: { required: true, message: '请输入卡拉云账号' },
    phone: {
        required: true,
        pattern: /^1\d{10}$/,
        message: "请输入卡拉云电话号码"
    },
    email: {
        required: true,
        pattern: /^([a-zA-Z0-9]+[_|_|\-|.]?)*[a-zA-Z0-9]+@([a-zA-Z0-9]+[_|_|.]?)*[a-zA-Z0-9]+\.[a-zA-Z]{2,6}$/,
        message: "请输入卡拉云邮箱"
    },
    password: { required: true, message: '请输入卡拉云密码' }
}

const handleBlurPhone = () => {
    validator.validate({ phone: form.value.phone }, (errors, fields) => {
        if (errors && fields.phone) {
            console.log(errors, fields);
            console.log(fields.phone[0].message);
            return errors
        }
    })
}
const handleBlurEmail = () => {
    validator.validate({ email: form.value.email }, (errors, fields) => {
        if (errors && fields.email) {
            console.log(errors, fields);
            console.log(fields.email[0].message);
            return errors
        }
    })
}

当然,测试是没有问题的

表单验证长度控制

假如你要控制表单输入内容的长度,可以使用属性 min 和 max,我们用 account 这个表单作为例子,我们 rules 对象的 account 中添加这两个属性,比如要求账号最少5个字符,最多10个字符,如下

account: { required: true, min:5, max:10, message: '请输入卡拉云账号' }

我们还可以使用 input 的原生属性 maxLength="10" 来控制用户的输入

表单内多个验证条件

当我们有多个验证条件的时候,我们可以把 rules 的验证条件写成一个数组,我们还是用 account 这个表单作为例子,比如 账号要求必须用中文,且账号最少5个字符,最多10个字符,代码如下

account: [
    { required: true, min:5, max:10, message: '请输入卡拉云账号' },
    { required: true, pattern: /[\u4e00-\u9fa5]/, message: '请输入中文卡拉云账号' }
],

自定义表单验证

有时候,我们会有使用自定义验证函数的情况,以满足特殊验证情况,这时候,我们可以这样做

field:{
    required: true,
    validator(rule, value, callback){
      return value === '卡拉云';
    },
    message: '值不等于 "卡拉云".',
}

到这里,vue3的表单验证功能雏形已经基本出来了,下面我们对验证功能进行完善

表单验证进一步优化完善

之前的表单验证虽然已经做出了,但是校验的提示信息是在控制台,这个很不友好,用户也看不到提示,所以这里我们完善下这部分功能

首先我们在 label 边加一个 "*" 表示必填,并且添加样式,给一个红色,醒目一些

<label class="ka-la-cloud-label">
    <span>账号</span>
    <span class="asterisk">&nbsp;*</span>
</label>


.asterisk{
    color: #d03050;
}

我们考虑到 rules 对象中 required 属性的作用,这里使用 vue 的条件判断语句 v-if 来判断,先定义一个函数,名字就叫 getRequired,然后将 rules.account,作为参数传进去,这里要重点说明一下,如果考虑封装验证方法,这里可以不用传参,不多说,后面讲到了,我们再说,先看代码

 <span class="asterisk" v-if="getRequired(rules.account)">&nbsp;*</span>

const getRequired = (condition) => {
    if(Object.prototype.toString.call(condition) === "[object Object]") {
        return condition.required
    } else if (Object.prototype.toString.call(condition) === "[object Array]") {
        let result = condition.some(item => item.required)
        return result
    }
    return false
}

因为 rules.account, 有可能是对象或者数组,这里我们加一个判断区别下,如果传递进来的是对象,我们直接将属性required返回回去,至于required属性是否存在,这里没有必要多判断。 如果传递进来的是数组,我们使用 some 函数获取下结果,然后再返回.

修改 rules.accountrequired 值为false,星号消失,这里只要有一个required 值为true,那么这个星号就显示

我们接着来添加错误信息的显示与隐藏

我们定义一个对象 modelControl,这个对象里面动态存储错误信息,

const modelControl = ref({})

接着给 accountinput 框添加一个自定义属性 prop, 属性值是 account, 再加一个div显示错误提示信息

<div class="form-group">
    <label class="ka-la-cloud-label">
        <span>账号</span>
        <span class="asterisk" v-if="getRequired(rules.account)">&nbsp;*</span>
    </label>
    <input v-model="form.account" type="text" maxLength="10" class="ka-la-cloud-input" prop="account" @blur="handleBlurAccount" placeholder="请输入卡拉云账号" />
    <div class="ka-la-cloud-input feedback" v-if="modelControl['account']">{{modelControl['account']}}</div>
</div>

.feedback{
    color: #d03050;
    font-size:14px;
    margin-top: 3px;
    text-align:left;
    margin-left:110px;
}

为了动态的显示和隐藏错误信息,我们需要修改失焦事件 和 submit 事件,在事件执行的时候,动态的将值赋予或清除,代码如下

const handleBlurAccount = (e) => {
    const prop = e.target.attributes.prop.value
    if (!prop) {
        return false
    }
    validator.validate({ account: form.value.account }, (errors, fields) => {
        if (errors && fields.account) {
            console.log(errors, fields);
            console.log(fields.account[0].message);

            modelControl.value[prop] = fields[prop][0].message
            return errors
        }
        modelControl.value[prop] = null
    })
}

validator.validate(form.value).then((value) => {
        // 校验通过
    console.log(value);
}).catch(({ errors, fields }) => {
    console.log(errors, fields);
    for(let key in fields) {
        modelControl.value[key] = fields[key][0].message
    }
    console.log(modelControl);
    return errors
})

到这里,表单的动态验证功能基本算是完成了,但是我们发现,每次错误信息的展示都会使得 input 框跳动,所以还得调整下样式:

.form-group {
    margin: 2px;
    padding: 10px 15px 3px 0;
    height:57px;
    transition: color .3s ease;
}

Vue form 表单验证并不复杂,只不过有非常多的情况需要考虑,本文的实例完整代码可在我们的 github 上找到。

Vue form 表单验证总结

本文详细讲解了 Vue form 表单在验证表单时会出现的多种情况,虽然我们调用第三方表单验证组件库已经帮我们简化了大量工作,但即便如此,前端调试有时也非常令人抓狂。如果不想处理前端问题,推荐使用卡拉云,卡拉云内置包括表单验证插件在内的各类组件,无需懂任何前端,仅需拖拽即可快速生成。

kalacloud-卡拉云 卡拉云内置表单组件,拖拽即用,填空配置表单校验,轻松完成表单验证。

下面是用卡拉云搭建的数据库 CURD 后台管理系统,只需拖拽组件,即可在10分钟内完成搭建。查看 3 分钟上手视频

卡拉云 SQL admin 后台管理系统

卡拉云是新一代低代码开发平台,与前端框架 Vue、React等相比,卡拉云的优势在于不用首先搭建开发环境,直接注册即可开始使用。开发者完全不用处理任何前端问题,只需简单拖拽,即可快速生成所需组件,可一键接入包括 MySQL 在内的常见数据库及 API,根据引导简单几步打通前后端,数周的开发时间,缩短至 1 小时。立即免费试用卡拉云