Vue3 表单校验最佳实践与常见坑
讲解 Vue3 表单校验的完整实践方案,对比手写校验、VeeValidate、Element Plus 内置校验等路径,涵盖常用规则配置、异步校验、自定义校验器、联动校验、提交前整体校验等内容,附代码示例与常见坑。
# Vue3 表单校验最佳实践与常见坑
> 表单校验看着简单,做起来全是细节:异步校验时序、联动规则、提交前校验……本文总结 Vue3 表单校验的最佳实践和踩过的坑。
## 一、三种校验方案对比
- **手写校验**:零依赖、灵活,但代码量大、易漏
- **VeeValidate**:Composition API 友好,规则丰富
- **UI 库内置**:Element Plus / Naive UI 自带,开箱即用
> 小表单手写即可;中大项目推荐 VeeValidate 或 UI 库内置。
## 二、Element Plus 基础用法
```vue
<template>
<el-form ref="formRef" :model="form" :rules="rules">
<el-form-item label="用户名" prop="username">
<el-input v-model="form.username" />
</el-form-item>
<el-form-item label="邮箱" prop="email">
<el-input v-model="form.email" />
</el-form-item>
</el-form>
</template>
<script setup>
const form = reactive({ username: "", email: "" });
const rules = {
username: [
{ required: true, message: "请输入用户名", trigger: "blur" },
{ min: 2, max: 20, message: "长度 2-20", trigger: "blur" }
],
email: [
{ required: true, message: "请输入邮箱", trigger: "blur" },
{ type: "email", message: "邮箱格式不正确", trigger: "blur" }
]
};
</script>
```
## 三、提交前整体校验
```js
const formRef = ref();
async function onSubmit() {
try {
// 校验所有字段,失败抛异常并滚动到第一个错误
await formRef.value.validate();
await submitApi(form);
} catch (err) {
console.error("校验未通过:", err);
}
}
```
## 四、自定义校验器
```js
// 手机号校验(简单示例)
const rules = {
phone: [
{
validator: (rule, value, callback) => {
if (!/^1[3-9]\d{9}$/.test(value)) {
callback(new Error("手机号格式不正确"));
} else {
callback();
}
},
trigger: "blur"
}
]
};
```
## 五、异步校验(用户名唯一性)
> ⚠️ **坑1:竞态问题**
快速输入时多个请求并发,后发先至导致校验结果错误。
```js
// 用防抖 + 校验序号解决
let checkSeq = 0;
async function checkUsername(name) {
const seq = ++checkSeq;
const exists = await api.checkUsername(name);
// 只有最新一次请求的结果才生效
if (seq === checkSeq) {
return exists ? "用户名已被占用" : true;
}
}
```
## 六、联动校验
> **坑2:字段间互相影响**
比如"确认密码"要和"密码"一致:
```js
const rules = {
confirmPassword: [
{
validator: (rule, value, callback) => {
if (value !== form.password) {
callback(new Error("两次密码不一致"));
} else {
callback();
}
},
trigger: "blur"
}
]
};
// 密码变化时,重新校验确认密码
watch(() => form.password, () => {
formRef.value.validateField("confirmPassword");
});
```
## 七、动态表单项
> **坑3:动态增删的校验规则**
```js
// 动态行校验:每行的邮箱都要校验
const form = reactive({ items: [{ email: "" }] });
function addItem() {
form.items.push({ email: "" });
}
function removeItem(i) {
form.items.splice(i, 1);
}
```
## 八、其他常见坑
- **trigger 用错**:输入时校验用 change/input,失焦用 blur,别混
- **v-model 未绑定 prop**:rules 里写了 prop,表单却忘了加 prop 属性
- **清空校验状态**:resetFields 前确认 form 已重新初始化
- **嵌套对象校验**:prop 用点路径,如 user.age
## 九、小结
表单校验的要点:
1. 提交前统一 validate
2. 异步校验注意竞态
3. 联动字段用 watch 触发重校验
4. 动态项校验规则随项走
把这些细节处理好,表单体验会扎实很多。