【element ui/vue】clearValidate('idCardNationalUrl'); 清除表单单项的验证不成功,结果把整个表单的验证都清除了

问题遇到的现象和发生背景

【element ui】图片上传控件,想要在上传之后能清除掉这单个的验证,但是结果是整个表单的验证都被清除了

问题相关代码,请勿粘贴截图
    <el-form-item label="身份证正面" prop="idCardNationalUrl" class="el-form-item2">

this.$nextTick(() => {
this.$refs.formEdit.clearValidate('idCardNationalUrl');
})

运行结果及报错内容

把整个表单的验证都清除了

我的解答思路和尝试过的方法
      this.$refs['formEdit'].clearValidate('idCardNationalUrl');
                this.$refs['formEdit'].clearValidate(['idCardNationalUrl']);

换不同的写法都试过了

我想要达到的结果

清除我传入的单个表单项验证

这个问题可以绕得开。
核心思路:在传图成功的同时通过更新绑定值+局部清除验证,来清除上传组件的验证信息。
关键步骤:
1、将 绑定值 与 图片地址参数同步,减少后边的重复操作:将imageUrl与上传组件的对应model同步,可用computed同步这两个值;
2、通过 绑定值+局部清除验证 解决上传控件的验证问题:在上传组件的handleAvatarSuccess函数中(on-success事件绑定的函数),更新this.imageUrl的值之后,需加代码消除验证,可用this.$refs.formRef.clearValidate("这里写上传组件所在的el-form-item的prop");
3、提交表单成功以后,避免再次“被验证”:提交成功要重置表单,但此时表单绑定的model被清空,重置的瞬间会再次触发验证!所以要再次清除表单验证,而且需使用setTimeout来调用this.$refs.formRef..clearValidate(),以避免同时触发导致的清空失败。

接下来的代码需要启动后端才能测出效果,Vue3+Node.js前后端分离,后端关键页面的代码也附上了。
希望能够帮到你,如果有写得不清楚的地方可以追加提问哟~

以下是前端代码:

<template>
  <div class="formDiv">
    <span class="tit">表单示例</span>
    <el-form
      ref="formRef"
      :model="formM"
      :rules="formRule"
      label-position="left"
      hide-required-asterisk
      :status-icon=false
    >
      <el-form-item prop="name" label="名称" >
        <el-input v-model="formM.name" type="input" ></el-input>
      </el-form-item> 

      <el-form-item prop="pic" label="图片" >
        <el-upload
          class="avatar-uploader"
          :action="baseURL + '/formSubmit/picUL'"
          :show-file-list="false"
          :on-success="handleAvatarSuccess"
          :before-upload="beforeAvatarUpload"
        >
          <img v-if="imageUrl" :src="imageUrl" class="avatar" />
          <el-icon v-else class="avatar-uploader-icon"><Plus /></el-icon>
        </el-upload>
      </el-form-item> 

      <el-form-item>
        <el-button type="primary" @click="submitForm()">提交</el-button>
      </el-form-item>

    </el-form>
  </div>
  <div class="hide">{{autoData}}</div>
</template>

<script>
import { ref } from 'vue';
import { ElMessage } from 'element-plus';
import { Plus } from '@element-plus/icons-vue';

export default {
  name: 'vq2',
  components:{Plus}, 
  data(){
    return{
      imageUrl: ref(''),
      formM: {name: "",pic:"",},
      formRule:{
        name: [
          {required: true, message: "名称不能为空", trigger: "change",},
          {min: 3, max: 8,
            validator(rule, value, callback) {
              if (value.length < rule.min || value.length > rule.max) {
                callback(new Error(`长度${rule.min}-${rule.max}位`));
              } else {callback();}
          },},],
        pic:[{required: true, message: "上传图片不能为空", trigger: "change",},],},}
  },
  computed:{
    autoData(){
      this.formM.pic=this.imageUrl; //自动刷新上传控件的表单绑定值
      return this.imageUrl;
    }
  },
  methods:{    
    handleAvatarSuccess(res, file){
      switch (res.code) {
        case 111:
          this.imageUrl = URL.createObjectURL(file.raw);
          ElMessage.success('图片上传成功!')
          break;
        default:
          this.imageUrl = ref('');
          ElMessage.error('图片上传失败')
      } 
      this.$refs.formRef.clearValidate("pic"); //消除验证
    },
    beforeAvatarUpload(file){
      const limitSize=2;
      const isJPG = /jpeg|jpg|png/.test(file.type);
      const isLt = file.size / 1024 / 1024 < limitSize;
      !isJPG&&this.showAlertM('图片格式jpeg、jpg、png');
      !isLt&&this.showAlertM('图片大小超过'+limitSize+'M');
      return isJPG && isLt;
    },
    submitForm(){ //提交
      let form=this.$refs.formRef;
      form.validate(async (valid) => {
        if (valid) {
          let validationAx = await this.$axios({
            method: "POST",
            url: "/formSubmit/FormDataUL",
            data:this.formM,
          });
          switch (validationAx.data.code) {
            case 111:
              this.imageUrl = ref('');
              form.resetFields(); //提交成功,重置表单
              window.setTimeout(()=>{form.clearValidate();},10);  //用定时器再清空一遍表单验证,是为了避免重置表单的同时触发验证导致验证清空失败的问题
              ElMessage.success('提交成功!');
              break;
            default:
              ElMessage.error('提交失败');
          } 
        } else {
          ElMessage.error('验证未通过');
          return false
        }
      })
    },
  },
}
</script>
<style lang="scss" scoped>
  .formDiv{
    position: relative;
    width: 500px;

    padding: 12px 0;
    
    margin: 24px auto ;

    border:1px solid rgba(125,125,125,0.1);
    border-radius: 7px;

    color:dodgerblue;

    display: flex;
    flex-flow: column nowrap;
    justify-content: space-evenly;
    align-items: center;

    &:hover{
      border-color:rgba(125,125,125,0.24);
      box-shadow: 1px 2px 1px rgba(125,125,125,0.01);
    }
  }
  .formDiv /deep/ .el-form {
    width: 100%;

    display: flex;
    flex-flow: column nowrap;
    justify-content: space-evenly;
    align-items: center;
  }
  .formDiv /deep/ .el-form-item{
    margin:0 0 24px;
    position: relative;

    &:nth-child(2){
      position: relative;
      left: -20px !important;
    }
    
  }
  .formDiv /deep/ .el-form-item__label{
    color: dodgerblue;
  }
  .tit{
    margin:0 0 12px;
  }
  .formDiv /deep/ .el-input__inner{
    width: 310px;
  }

  .avatar-uploader /deep/ .el-upload {
    border: 1px dashed #d9d9d9;
    border-radius: 6px;
    cursor: pointer;
    position: relative;
    overflow: hidden;
    transition: var(--el-transition-duration-fast);
    width: 178px;
    height: 178px;
  }
  .avatar-uploader /deep/ .el-upload:hover {
    border-color: var(--el-color-primary);
  }
  .avatar-uploader /deep/ .el-icon.avatar-uploader-icon {
    font-size: 28px;
    color: #8c939d;
    width: 178px;
    height: 178px;
    text-align: center;
  }
  .avatar{
    display: block;
    width: auto;
    height: 178px;
  }
  .el-alert{
    position:fixed;
    top:24px;
    margin: 20px 0 0;
    padding: 0 50px;
    width: auto;
    height:auto;
    overflow:visible;

    transition: all 0.7s ease-in-out;
  }
  .el-alert:first-child {
    margin: 0;
  }

  .hide{
    visibility: hidden;
  }
</style>

以下是后端代码,文件名为formSubmit.js,是路由的内容,需要将这个路由添加到router/index.js才能生效,具体方法我就不赘述了:

const express= require("express");
const router= express.Router();

router.post("/picUL",async (req,res)=>{
    let reqData=req.body;
     res.send({
                code:111,
                message:"提交成功",
                data:reqData,
    });
});

router.post("/FormDataUL",async (req,res)=>{
    let reqData=req.body;
     res.send({
                code:111,
                message:"提交成功",
                data:reqData,
    });
});

module.exports=router;