async-validator 是个表单校验库
安装async-validator
npm i async-validator
我们的目标完成一个表单验证,如下:
上代码:
先定义一个hooks,validator.ts 里面封装了async-validator的validate方法,底下有2个辅助函数是为了在界面展示错误信息
import AsyncValidator, { type Rules } from 'async-validator'
/**
*
* @param value 整个表单值
* @param rules 校验规则
* @param key 传入key 怎验证单行,否则验证整个表单
* @returns
*/
export const useValidator = (form: any, rules: Rules, key?: string) => {
let _rules: any = {}
if (key) {
_rules[key] = rules[key]
} else {
_rules = rules
}
const validator: AsyncValidator = new AsyncValidator(_rules)
return validator
.validate(form.value)
.then(() => {
// 验证通过
clearErrorMsg(form, key)
return { valid: true }
})
.catch(({ errors }) => {
setErrorMsg(errors, form, key)
return { valid: false, errors }
})
}
// 设置界面错误展示信息
const setErrorMsg = (errors: any, form: any, key?: string) => {
if (key) {
form.value[key + 'Msg'] = errors[0].message
} else {
errors.forEach((error: { field: string; message: any }) => {
form.value[error.field + 'Msg'] = error.message
})
}
}
// 验证通过将错误置空
const clearErrorMsg = (form: any, key?: string) => {
if (key) {
form.value[key + 'Msg'] = ''
} else {
Object.keys(form.value).forEach((itemKey) => {
if (itemKey.endsWith('Msg')) {
form.value[itemKey + 'Msg'] = ''
}
})
}
}
表单组件 ValidatorView.vue
<template>
<div class="main">
<h2>vue3 表单验证</h2>
<form>
<div>
<label class="label">账号</label>
<a-input
type="text"
v-model:value="form.account"
@blur="handleBlurAccount"
placeholder="请输入账号"
class="input"
/>
<div class="error">{{ form.accountMsg }}</div>
</div>
<div>
<label class="label">密码</label>
<a-input
tyep="password"
v-model:value="form.password"
@blur="handleBlurPassword"
type="text"
class="input"
placeholder="请输入密码"
/>
<div class="error">{{ form.passwordMsg }}</div>
</div>
<div>
<a-button class="submit-btn" type="primary" @click="submit">保存</a-button>
</div>
</form>
</div>
</template>
<script lang="ts" setup>
import { ref } from 'vue'
import { Input as AInput, Button as AButton } from 'ant-design-vue'
import { useValidator } from '@/hooks/validator'
// 验证表单
const form = ref({
account: '',
password: '',
accountMsg: '', // 用来展示错误信息
passwordMsg: '' // 用来展示错误信息
})
// 验证规则
const rules = {
account: [{ required: true, message: '请输入账号' }],
password: [{ required: true, message: '请输入密码' }]
}
// 验证函数
const validatorFn = (key?: string) => {
return useValidator(form, rules, key)
}
// 账户失去焦点验证,单个表单行校验
const handleBlurAccount = () => {
validatorFn('account')
}
// 密码失去焦点验证,单个表单行
const handleBlurPassword = () => {
validatorFn('password')
}
// 验证整个表单
const submit = () => {
validatorFn().then((result: any) => {
if (result.valid) {
console.log('验证通过!', form.value)
} else {
console.log('验证失败', result.errors)
}
})
}
</script>
<style lang="css">
.main {
margin: 10px 100px;
}
.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;
}
.submit-btn {
margin-top: 10px;
margin-left: 100px;
}
.error {
color: red;
height: 20px;
margin-left: 100px;
font-size: 12px;
}
</style>
在组件中,定义一个需要验证的表单form,并将form的属性绑定到表单元件input上去。还需要定义验证规则,验证规则跟form字段对应,然后定义了一个验证函数validatorFn,在需要验证的时机调它,validatorFn调用我们定义的hooks
这时候我们点击提交,看下控台,验证通过和不通过输出分别如下:
如果有异步验证只需要增加一条带asyncValidator的规则:
// 验证规则
const rules = {
account: [
{ required: true, message: '请输入账号' },
{
message: '账号已存在',
asyncValidator: (_rule: any, value: string) => {
return new Promise<void>((resolve, reject) => {
setTimeout(() => {
if (value === 'abc') {
reject('isExist') // reject with error message
} else {
resolve()
}
}, 500)
})
}
}
],
password: [{ required: true, message: '请输入密码' }]
}
这时候可以加个loading属性,点击submit后出现一个loading效果,验证结束后消失
<div>
<a-button class="submit-btn" type="primary" @click="submit">保存</a-button>
<span v-if="loading" class="loading">验证中...</span>
</div>
const loading = ref(false);
// 验证整个表单
const submit = () => {
loading.value = true;
validatorFn().then((result: any) => {
loading.value = false;
if (result.valid) {
console.log('验证通过!', form.value)
} else {
console.log('验证失败', result.errors)
}
})
}
效果如图:
以上就是自定义的表单验证内容,代码可以直接复制运行