vue3 + async-validator实现表单验证的示例代码
作者:知见秋 发布时间:2024-05-09 15:24:03
vue3 表单验证
前言
表单验证可以有效的过滤不合格的数据,减少服务器的开销,并提升用户的使用体验。
今天我们使用 vue3 来做一个表单验证的例子。先来看看完成的效果图
搭建vue3的项目
创建项目前 这里我们首先要说明的是,我们使用的版本情况
Nodejs:v17.5.0
pnpm:7.0.0
Vue:3.2.25
首先我们 Vite 创建一个 vue3 的项目demo,名字就叫 FormValidate, 我们在命令行输入命令
pnpm create vite FormValidate
回车
然后选择 vue
继续回车,说明我们已经初步创建了 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/
ok, 到这里我们已经把项目搭建起来了,结下来我们就开始来说说我们今天主题-表单验证
vue3的表单验证
这里我们使用 async-validator 这是个异步验证表单的插件,在github上有 5k+ 的star,使用的也很广泛,比如 Ant.design
,Element UI
, Naive UI
等都在使用这个插件,甚至与有些Nodejs后端项目也在使用这个。
先安装一下这个插件,在命令行输入
pnpm install async-validator
这里 async-validator
版本是 4.1.1
1.表单代码
打开项目中的 App.vue 文件,删除多余的文件内容,输入标题 vue3 表单验证,并添加一些初始代码
<template>
<div class="main">
<h3>vue3 表单验证</h3>
<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>
是不是看起来有点丑,别急,我们加点css代码,简单的美化一下
<template>
<div class="main">
<h3>Vue3表单验证</h3>
<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" />
// 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="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="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
}
})
}
2-2. 多个表单的验证
当然这里校验的只是单个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
}
})
}
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: /^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
}
})
}
当然,测试是没有问题的
2-5. 长度控制
假如你要控制表单输入内容的长度,可以使用属性 min 和 max,我们用 account 这个表单作为例子,我们 rules 对象的 account 中添加这两个属性,比如要求账号最少5个字符,最多10个字符,如下
account: { required: true, min:5, max:10, message: '请输入账号' }
我们还可以使用 input 的原生属性 maxLength="10" 来控制用户的输入
2-6. 多个验证条件
当我们有多个验证条件的时候,我们可以把 rules 的验证条件写成一个数组,我们还是用 account 这个表单作为例子,比如 账号要求必须用中文,且账号最少5个字符,最多10个字符,代码如下
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: '值不等于 "".',
}
到这里,vue3的表单验证功能雏形已经基本出来了,下面我们对验证功能进行完善
3.优化完善
之前的表单验证虽然已经做出了,但是校验的提示信息是在控制台,这个很不友好,用户也看不到提示,所以这里我们完善下这部分功能
首先我们在 label 边加一个 "*" 表示必填,并且添加样式,给一个红色,醒目一些
<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;
}
为了动态的显示和隐藏错误信息,我们需要修改失焦事件 和 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;
}
来源:https://juejin.cn/post/7102055792634757133


猜你喜欢
- 1.引言本文是Python生态系统中一些有用技巧的分享。大多数技巧只是使用标准库中的包,但其他一些技巧会涉及一些第三方包。在开始阅读本文内容
- 这篇文章主要介绍了Python matplotlib画曲线例题解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价
- Web框架把我们从WSGI中拯救出来了。现在,我们只需要不断地编写函数,带上URL,就可以继续Web App的开发了。但是,Web App不
- 版本更新,原来user里的password字段已经变更为authentication_string版本更新 缘故,好多网上的教程都不适用了,
- Translate From:stevesouders原文:高性能网站设计:不要使用@import在高性能网站设计的第五章,我简要的提到@i
- 本文实例讲述了Flask框架实现的前端RSA加密与后端Python解密功能。分享给大家供大家参考,具体如下:前言在使用 Flask 开发用户
- 这是我自己做的一个轮播图,大家可以看看 ,我还没进行优化.有改进的地方可以私聊布局什么的你们自己搞定吧<div class="
- 业务需求:需要测试手机滑动解锁失败时事件的次数及等待的时间,本来想利用Python+Appium实现,但是Appium运行时自动给我解锁了.
- asp代码 如下:读取注册表信息使用了对象WScript.Shell<%Dim strPath strP
- 本文实例讲述了python中查看变量内存地址的方法。分享给大家供大家参考。具体实现方法如下:这里可以使用id>>> pri
- #!/usr/bin/env python# -*- coding: utf-8 -*-import os, base64ico
- 前几天和一个小伙伴交流了一下nodejs中epoll和处理请求的一些知识,今天简单来聊一下nodejs处理请求的逻辑。我们从listen函数
- 使用jmail组件发送邮件:Function JMail(Send_From,Send_To,Send_Subject,Send_
- 一、架构介绍Scrapy一个开源和协作的框架,其最初是为了页面抓取 (更确切来说, 网络抓取 )所设计的,使用它可以以快速、简单、可扩展的方
- python默认使用的是国外镜像,有时候下载非常慢,最快的办法就是在下载命令中增加国内源:常用的国内源如下:清华大学:https://pyp
- 本文为大家分享了TensorFLow用Saver保存和恢复变量的具体代码,供大家参考,具体内容如下建立文件tensor_save.py, 保
- Firefox 的 Jetpack 可以让我们很轻松地创建 Firefox 插件,仅通过已掌握的前端技能(HTML/CSS/JS),估计让人
- 引言最近再做图像处理相关的操作的时间优化,用到了OpenCV和Pillow两个库,两个库各有优缺点。各位小伙伴需要按照自己需求选用。本篇博客
- 本文为大家分享了python银行管理系统的具体代码,供大家参考,具体内容如下自己写的练手小程序,练习面向对象的概念,代码中都有注释,刚学的同
- 下面方法可以用来快速生成一批数据 if(object_id('t') is not null) drop table t g