先上效果图
实现功能
- 必填项校验,鼠标失去焦点时提示 “不可以为空”
- 特殊校验如手机号,鼠标失去焦点时根据相应校验规则提示相应信息
- 用户提交表单前需勾选☑️已阅读
- 提交表单时 ,统一校验,根据规则提示相应信息
实现原理
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>
现在一个表单的基本结构已经完成,样式比较简单这里就不展示代码了(最后会给出所有代码)
添加表单校验
- 引入async-validator
- 根据表单校验规则定义一个对象rules,对象内包含校验规则和校验不通过的信息提示,每个对象都可以配置多条校验规则,也可以自定义校验规则
- 实例化 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>
- 验证单个表单
给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;
});
}
- 我正在参与掘金技术社区创作者签约计划招募活动,点击链接报名投稿。