在开发中,遇到这个需求:前端表单通过初步校验发送给后端,但后端业务逻辑(如:数据库查重、时间冲突等)返回了具体的错误信息。业务希望将这些错误直接显示在 el-form-item 的错误提示位置。大概效果如下:

基础校验如下
javascript
const rules = ref({
start_time: [{ required: true, message: "请输入时间", trigger: "blur" }],
location: [{ required: true, message: "请输入地点", trigger: "blur" }],
pant: [{ required: true, message: "请输入参与者", trigger: "blur" }],
evt_desc: [
{ required: true, message: "请请输入描述", trigger: "blur" },
{ min: 0, max: 30, message: "描述不超过 30 个字符", trigger: "blur" },
],
});
遇到的问题:
直接给 :error 属性赋值,首次没问题,错误正产显示,但第二次点击提交时校验消息就不再显示了。
原因:Element Plus 的 el-form-item 提供了 :error 属性。
当给这个属性赋值时,它会强制显示该错误提示,并覆盖原有的 rules 校验信息。
因为form.validate() 是异步过程,其内部维护的校验状态更新可能与手动赋值 :error 的操作产生竞争关系,导致手动赋的值被组件内部逻辑重置。
解决使用 nextTick(或延时)确保后端错误能稳定渲染
代码示例:
javascript
<template>
<div>
<el-form ref="formRef" :model="form" :rules="rules" label-position="top">
<el-form-item label="事件描述" prop="evt_desc" :error="backendErrors.evt_desc">
<el-input v-model="form.evt_desc" placeholder="请输入描述" />
</el-form-item>
<el-button type="primary" :loading="loading" @click="handleSubmit">
开始
</el-button>
</el-form>
</div>
</template>
<script setup>
import { reactive, ref, nextTick } from 'vue';
const formRef = ref();
const loading = ref(false);
// 存储后端返回的错误映射
const backendErrors = reactive({
evt_desc: ""
});
const form = reactive({
evt_desc: ""
});
const rules = {
evt_desc: [{ required: true, message: "前端校验:请输入内容", trigger: "blur" }]
};
// 模拟后端接口
async function mockApi() {
return new Promise((_, reject) => {
setTimeout(() => {
// 模拟后端校验不通过返回的数据
reject({
message: JSON.stringify({ evt_desc: "后端反馈:该描述已存在,请更换" })
});
}, 500);
});
}
// 提交逻辑
async function handleSubmit() {
if (!formRef.value) return;
formRef.value.validate(async (valid) => {
if (!valid) return;
loading.value = true;
try {
await mockApi();
// 成功逻辑...
} catch (err) {
// 清空旧的后端错误
Object.keys(backendErrors).forEach(key => backendErrors[key] = "");
// 解析错误并赋值
const errorMap = JSON.parse(err.message);
// ==== 这个是关键 ====
await nextTick();
for (const key in errorMap) {
if (key in backendErrors) {
backendErrors[key] = errorMap[key];
}
}
} finally {
loading.value = false;
}
});
}
</script>