问题描述:
我是vue3+vite+ts, 添加用户没问题, 修改用户的表单校验有问题, 表单符合规则但是await formRef.value.validate()始终不通过
html结构:
<el-drawer v-model="drawer" :title="userParams.id?'修改用户':'添加用户'">
<el-form ref="formRef" :model="userParams" :rules="rules">
<el-form-item prop="username" label="用户姓名">
<el-input v-model="userParams.username" type="text"></el-input>
</el-form-item>
<el-form-item prop="name" label="用户昵称">
<el-input v-model="userParams.name" type="text"></el-input>
</el-form-item>
<el-form-item prop="password" v-show="!userParams.id" label="用户密码">
<el-input v-model="userParams.password" type="text"></el-input>
</el-form-item>
</el-form>
<template #footer>
<el-button @click="cancelClick">取消</el-button>
<el-button type="primary" @click="confirmClick">确定</el-button>
</template>
</el-drawer>
js代码:
import { onMounted, ref ,nextTick, reactive} from 'vue'
import {reqUserInfo , reqAddOrUpdateUser} from '../../../api/acl/user'
import { SetRoleData, UserResponseData, Records, User, AllRoleResponseData, AllRole } from '../../../api/acl/user/type.ts';
import { ElMessage } from 'element-plus';
import { ResponseData } from '../../../api/user/type.ts';
let drawer = ref(false) //控制抽屉的显示与隐藏
let userParams = reactive<User>({
username:'',
name:'',
password:''
})
let formRef = ref()
// 自定义表单校验username和name
const validateUserNameOrName = (rule: any, value: any, callBack: any)=>{
const usernameRegex = /^(?!\d+$)(?![a-zA-Z]+$).+$/;
if (!usernameRegex.test(value) && value !== '') {
callBack(new Error('不能仅由字母或数字组成'));
}
else if(value == 'admin'){
callBack(new Error('用户名已存在'));
}else{
callBack();
}
}
// 自定义表单校验password
const validateUserPassword = (rule: any, value: any, callBack: any)=>{
const passwordRegex = /^(?=.*[a-zA-Z])(?=.*\d).+$/;
if (!passwordRegex.test(value)) {
return callBack(new Error('密码至少包含字母和数字'));
}else{
callBack();
}
}
// 表单校验规则属性
const rules = {
username:[
{required:true,message:'请输入用户名',trigger:'blur'},
{min:2,max:13,message:'用户长度请控制在2-13位',trigger:'blur'},
{trigger:'blur',validator:validateUserNameOrName}
],
name:[
{required:true,message:'请输入用户昵称',trigger:'blur'},
{min:2,max:13,message:'用户长度请控制在2-13位',trigger:'blur'},
{trigger:'blur',validator:validateUserNameOrName}
],
password:[
{required:true,message:'请输入密码',trigger:'blur'},
{min:6,max:13,message:'用户长度请控制在6-13位',trigger:'blur'},
{trigger:'blur',validator:validateUserPassword}
]
}
// 获取已有用户信息
const getHasUser =async()=>{
let res:UserResponseData = await reqUserInfo(currentPage.value , pageSize.value)
if(res.code ==200){
total.value = res.data.total
userArr.value = res.data.records
}
}
// 添加用户按钮
const addUser = async()=>{
// 每次进来清空上次收集表单数据
Object.assign(userParams,
{
id:'',
username:'',
name:'',
password:''
}
)
// 清理之前的校验信息
nextTick(()=>{
formRef.value.clearValidate('username');
formRef.value.clearValidate('name');
formRef.value.clearValidate('password');
})
drawer.value = true
}
// 编辑按钮修改用户信息
const updateUser =(row:User)=>{
// 清理之前的校验信息
nextTick(()=>{
formRef.value.clearValidate('username');
formRef.value.clearValidate('name');
})
drawer.value = true
// 每次进来绑定当前用户对象row的表单数据
Object.assign(userParams,row)
console.log(formRef);
}
// 抽屉的取消按钮
const cancelClick = ()=>{
drawer.value = false
}
// 抽屉的确定按钮
const confirmClick = async() =>{
try {
await formRef.value.validate()
drawer.value = false
let res:any = await reqAddOrUpdateUser(userParams)
if(res.code == 200 ){
ElMessage({
type:'success',
message:userParams.id?"修改成功":"添加成功"
})
drawer.value = false
getHasUser()
}else{
drawer.value = false
ElMessage({
type:'error',
message:userParams.id?"修改失败":"添加失败"
})
}
} catch (error) {
ElMessage({
type:'error',
message:"表单校验不通过"
})
}
}
onMounted(()=>{
getHasUser()
})
破案了:
html结构中v-show应该改为v-if, 至于他们俩的区别我想就不多说了, 点击修改按钮的时候row中的password赋给了userParams(这个值可能是不符合你的表单规范的), 由于v-show的原理是控制display:none的, 所以其实做修改用户的表单校验时候不仅校验了用户名和昵称,也校验了password(即使他被我隐藏了), 而v-if销毁了
<el-form-item prop="password" v-if="!userParams.id" label="用户密码">
<el-input v-model="userParams.password" type="text"></el-input>
</el-form-item>
这个item组件就不会引发prop="password"这个字段的校验