【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>
相关推荐
研☆香9 分钟前
分析制作html页面,如何划分页面结构
前端
kyriewen31 分钟前
我扒了最近的前端面经——2026年面试不背八股文了,考这5样
前端·面试·ai编程
IT_陈寒1 小时前
Redis的持久化配置把我坑惨了:你以为数据安全了?
前端·人工智能·后端
小徐_23331 小时前
uni-app 项目别再从零搭了!3 个 Wot UI 起手模板怎么选?
前端·uni-app
张元清1 小时前
React useResizeObserver Hook:追踪元素尺寸变化(2026)
javascript·react.js
赵庆明老师2 小时前
Vben精讲:16-熟悉Vite前端工具链
前端
瑞瑞小同学4 小时前
处理echarts x轴内容过多,重叠问题
前端·javascript·echarts
HexCIer4 小时前
面向未来的原子化 CSS:UnoCSS 核心架构分析与 Tailwind CSS 现状
前端·css·vite
程序员黑豆4 小时前
鸿蒙应用开发中的单位详解:px、vp、fp、lpx
前端·harmonyos
像我这样帅的人丶你还5 小时前
MCP + npm:给五年前的老系统接上AI
前端·javascript·agent