【Vue3】Element Plus 表单显示自定义校验错误

在开发中,遇到这个需求:前端表单通过初步校验发送给后端,但后端业务逻辑(如:数据库查重、时间冲突等)返回了具体的错误信息。业务希望将这些错误直接显示在 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>
相关推荐
linweidong8 分钟前
C++ 模块化编程(Modules)在大规模系统中的实践难点?
linux·前端·c++
leobertlan4 小时前
2025年终总结
前端·后端·程序员
子兮曰4 小时前
OpenClaw架构揭秘:178k stars的个人AI助手如何用Gateway模式统一控制12+通讯频道
前端·javascript·github
Howrun7774 小时前
VSCode烦人的远程交互UI讲解
ide·vue.js·vscode
百锦再5 小时前
Reactive编程入门:Project Reactor 深度指南
前端·javascript·python·react.js·django·前端框架·reactjs
莲华君5 小时前
React快速上手:从零到项目实战
前端·reactjs教程
百锦再5 小时前
React编程高级主题:测试代码
android·前端·javascript·react.js·前端框架·reactjs
易安说AI5 小时前
Ralph Loop 让Claude无止尽干活的牛马...
前端·后端
颜酱6 小时前
图结构完全解析:从基础概念到遍历实现
javascript·后端·算法
失忆爆表症7 小时前
05_UI 组件库集成指南:Shadcn/ui + Tailwind CSS v4
前端·css·ui