vue3+async-validator如何实现表单验证
时间:2023-05-11 12:32
创建项目前 这里我们首先要说明的是,我们使用的版本情况 首先我们 Vite 创建一个 vue3 的项目demo,名字就叫 FormValidate, 我们在命令行输入命令 然后选择 vue 继续回车,说明我们已经初步创建了 FormValidate (表单验证)项目 根据命令行的提示,我们进入项目根目录,然后使用命令 接着,我们启动项目 启动浏览起,输入地址 ok, 到这里我们已经把项目搭建起来了,结下来我们就开始来说说我们今天主题-表单验证 这里我们使用 async-validator 这是个异步验证表单的插件,在github上有 5k+ 的star,使用的也很广泛,比如 先安装一下这个插件,在命令行输入 这里 打开项目中的 App.vue 文件,删除多余的文件内容,输入标题 vue3 表单验证,并添加一些初始代码 是不是看起来有点丑,别急,我们加点css代码,简单的美化一下 引入 根据表单的情况,我们定义一个对象,这个对象里面存储了需要校验的对象和校验不通过时的信息 实例化 Schema, 将 rules 传入 Schema,得到一个 validator 验证单个表单我们使用 失去焦点事件, 定义一个函数,将这个函数添加到 account input上的失焦事件上 接着将实例化后的校验器函数写到 handleBlurAccount 中 在account 的 input 中测试,我们可以看到在控制台打印出了 请输入账号 等字 同样的,我们给密码框也添加如下代码 当然这里校验的只是单个input的,我们接下来说说多个表单的校验,定义一个点击事件为submit,将submit事件添加到button上,当然不要忘记阻止浏览器默认事件 了上面的方式, 点击保存,同样的,我们可以看到控制台已经打印了错误信息,说明我们写的是合适的 当然有时候我们会输入邮箱,电话号码等表单,这时候我们就需要添加正则来进行验证了,我们先添加两个表单,并添加失焦事件, 正则验证需要用到 当然,测试是没有问题的 假如你要控制表单输入内容的长度,可以使用属性 min 和 max,我们用 account 这个表单作为例子,我们 rules 对象的 account 中添加这两个属性,比如要求账号最少5个字符,最多10个字符,如下 我们还可以使用 input 的原生属性 maxLength="10" 来控制用户的输入 当我们有多个验证条件的时候,我们可以把 rules 的验证条件写成一个数组,我们还是用 account 这个表单作为例子,比如 账号要求必须用中文,且账号最少5个字符,最多10个字符,代码如下 有时候,我们会有使用自定义验证函数的情况,以满足特殊验证情况,这时候,我们可以这样做 到这里,vue3的表单验证功能雏形已经基本出来了,下面我们对验证功能进行完善 之前的表单验证虽然已经做出了,但是校验的提示信息是在控制台,这个很不友好,用户也看不到提示,所以这里我们完善下这部分功能 首先我们在 label 边加一个 "*" 表示必填,并且添加样式,给一个红色,醒目一些 我们考虑到 因为 修改 我们接着来添加错误信息的显示与隐藏 我们定义一个对象 接着给 为了动态的显示和隐藏错误信息,我们需要修改失焦事件 和 submit 事件,在事件执行的时候,动态的将值赋予或清除,代码如下 到这里 表单的动态验证功能基本算是完成了,但是我们发现,每次错误信息的展示都会使得input框跳动,所以还得调整下样式 以上就是vue3+async-validator如何实现表单验证的详细内容,更多请关注Gxl网其它相关文章!搭建vue3的项目
Nodejs:v17.5.0
pnpm:7.0.0
Vue:3.2.25
pnpm create vite FormValidate
回车pnpm install
安装项目需要的依赖,当然这里使用 pnpm 是比 npm 或者 yarn 快很多的。pnpm run dev
, 终端中输出如图内容 vite v2.9.7 dev server running at: > Local: http://localhost:3000/ > Network: use `--host` to expose ready in 954ms.
http://localhost:3000/
vue3的表单验证
Ant.design
,Element UI
, Naive UI
等都在使用这个插件,甚至与有些Nodejs后端项目也在使用这个。pnpm install async-validator
async-validator
版本是 4.1.1
1.表单代码
<template> <div class="main"> <h4>vue3 表单验证</h4> <form> <div> <label class="label">账号</label> <input type="text" placeholder="请输入账号" class="input" /> </div> <div> <label class="label">密码</label> <input tyep="password" type="text" class="input" placeholder="请输入密码" /> </div> <div> <button>保存</button> </div> </form> </div></template><script setup></script><style lang="css">.main{ text-align:center;}.label { padding-right: 10px; padding-left: 10px; display: inline-block; box-sizing: border-box; width: 100px; text-align: right;}.input { width: 200px; height: 30px; margin-top:10px;}</style>
<template> <div class="main"> <h4>Vue3表单验证</h4> <form class="form-box"> <div class="form-group "> <label class="label">账号</label> <input type="text" class="input" placeholder="请输入账号" /> </div> <div class="form-group"> <label class="label">密码</label> <input tyep="password" type="text" placeholder="请输入密码" class="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}.label { padding-right: 10px; padding-left: 10px; display: inline-block; box-sizing: border-box; width: 110px; text-align: right;}.input { width: calc(100% - 120px); height: 28px;}</style>
2.添加验证
2-1. 初始化
ref
属性和 async-validator
,这里我们给每个 input 框添加 v-model
绑定属性,// html<input type="text" v-model="form.account" class="input" placeholder="请输入账号" /><input tyep="password" v-model="form.password" type="text" placeholder="请输入密码" class="input" />// scriptimport { 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: '请输入密码' }}
const validator = new Schema(rules)
// html<input v-model="account" type="text" class="input" @blur="handleBlurAccount" placeholder="请输入账号" />// scriptconst handleBlurAccount = () => {}
const handleBlurAccount = () => { validator.validate({account: form.value.account}, (errors, fields) => { if (errors && fields.account) { console.log(fields.account[0].message); return errors } })}
//html<input v-model="form.password" tyep="password" type="text" @blur="handleBlurPassword" placeholder="请输入密码" class="input" />//scriptconst 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 } })}
2-2. 多个表单的验证
const submit = (e) => { e.preventDefault(); validator.validate(form.value, (errors, fields) => { if (errors) { for(let key of errors) { console.log(key.message); } return errors } })}
2-3. Promise方式验证
async-validator
还提供 Promise 的方式,我们把 submit 函数中的代码修改为如下validator.validate(form.value).then((value) => { // 校验通过 console.log(value);}).catch(({ errors, fields }) => { console.log(errors); return errors})
2-4. 正则验证
async-validator
的属性 pattern,我们将符合要求的正则添加到 rules ,代码如下所示<div class="form-group "> <label class="label">电话号码</label> <input v-model="form.phone" type="text" class="input" @blur="handleBlurPhone" placeholder="请输入电话号码" /></div><div class="form-group "> <label class="label">邮箱</label> <input v-model="form.email" type="text" class="input" @blur="handleBlurEmail" placeholder="请输入邮箱" /></div>const form = ref({ account: null, email: null, password: null,})const rules = { account: { required: true, message: '请输入账号' }, phone: { required: true, pattern: /^1d{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 } })}
2-5. 长度控制
account: { required: true, min:5, max:10, message: '请输入账号' }
2-6. 多个验证条件
account: [ { required: true, min:5, max:10, message: '请输入账号' }, { required: true, pattern: /[u4e00-u9fa5]/, message: '请输入中文账号' }],
2-5. 自定义验证
field:{ required: true, validator(rule, value, callback){ return value === ''; }, message: '值不等于 "".',}
3.优化完善
<label class="label"> <span>账号</span> <span class="asterisk"> *</span></label>.asterisk{ color: #d03050;}
rules
对象中 required
属性的作用,这里使用 vue 的条件判断语句 v-if
来判断,先定义一个函数,名字就叫 getRequired
,然后将 rules.account
,作为参数传进去,这里要重点说明一下,如果考虑封装验证方法,这里可以不用传参,不多说,后面讲到了,我们再说,先看代码 <span class="asterisk" v-if="getRequired(rules.account)"> *</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.account
的 required
值为false,星号消失,这里只要有一个required
值为true,那么这个星号就显示modelControl
,这个对象里面动态存储错误信息,const modelControl = ref({})
account
的 input
框添加一个自定义属性 prop
, 属性值是 account
, 再加一个div显示错误提示信息<div class="form-group"> <label class="label"> <span>账号</span> <span class="asterisk" v-if="getRequired(rules.account)"> *</span> </label> <input v-model="form.account" type="text" maxLength="10" class="input" prop="account" @blur="handleBlurAccount" placeholder="请输入账号" /> <div class="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;}
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})
.form-group { margin: 2px; padding: 10px 15px 3px 0; height:57px; transition: color .3s ease;}