• ElementPlus非表单组件ElUpload值更新后校验不消失问题


    项目场景:

    在这里插入图片描述
    el-form表单中有一个上传组件,有必填校验。

    问题描述

    先触发表单的必填校验(点击提交按钮),然后再上传文件,必填校验的提示一直存在,如果再次点击提交,手动触发表单校验,必填校验消失,说明表单中的值是改变了的,但是值改变没有触发校验。
    在这里插入图片描述

    原因分析:

    对于常规的表单组件,例如ElInput、ElSelect,如果值改变,是会自动触发表单校验的,可以在rule中设置trigger属性,如果为change,那么就是值改变后触发,如果是blur,那么就是失去焦点后触发,如果没有设置该属性,那么无论是change还是blur都会触发校验。

    但是对于非表单元素,例如上传组件ElUpload或者我们自己写的不包含表单组件的自定义组件,值变化后,没有办法自动触发该项表单的校验,也就是给表单传递change或者blur事件。

    所以我们需要在组件的值变化后,手动触发该表单项的校验。

    解决方案:

    网上有很多解决办法,比如监听值得变化后,重新调用表单的校验方法,或者用一个隐藏的表单组件,来达到值变化后触发校验的目的。

    去看了element的源码之后,发现其实有一种更加简单的办法,可以直接在表单组件闭环校验,我们只需要使用组件即可,不需要关心组件双向绑定值变化后去去除校验提示。

    自定义上传组件:CustomUpload.vue

    <template>
      <el-upload
        ref="uploadRef"
        :on-change="handleChange"
        :auto-upload="false"
        v-model:file-list="fileList"
      >
        <template #trigger>
          <el-button type="primary">select file</el-button>
        </template>
    
        <template #tip>
          <div class="el-upload__tip">
            jpg/png files with a size less than 500kb
          </div>
        </template>
      </el-upload>
    </template>
    
    <script lang="ts" setup>
    import { ref } from 'vue'
    import { useFormItem } from 'element-plus'
    import type { UploadInstance } from 'element-plus'
    
    const { formItem } = useFormItem()
    
    const props = defineProps(['modelValue'])
    const emits = defineEmits(['update:modelValue'])
    
    const uploadRef = ref<UploadInstance>()
    
    const fileList = ref([])
    
    const handleChange = () => {
      // 模拟上传成功后,更新表单双向绑定值
      setTimeout(() => {
        console.log('文件上传成功:', fileList.value)
        emits('update:modelValue', fileList.value)
        // 关键代码,validate可以设置参数为change和blur,对应rule中的trigger
        formItem?.validate('').catch((err) => console.log(err))
      })
    }
    </script>
    

    表单中使用该组件:Form.vue

    <template>
      <el-form ref="formRef" :model="formData" :rules="fromRule">
        <el-form-item label="上传文件" prop="fileList">
          <CustomUpload v-model="formData.fileList" />
        </el-form-item>
      </el-form>
      <el-button @click="handleSubmit">提 交</el-button>
    </template>
    
    <script setup lang="ts">
    import { ref } from 'vue'
    
    import CustomUpload from './Upload.vue'
    
    const formRef = ref()
    const formData = ref({
      fileList: []
    })
    const fromRule = {
      fileList: [
        {
          required: true,
          message: '请上传文件',
        }
      ]
    }
    const handleSubmit = async () => {
      try {
        console.log(formData.value)
        await formRef.value.validate()
      } catch (error) {
        //
      }
    }
    </script>
    
    <style lang="scss" scoped>
    
    </style>
    

    看下效果:
    请添加图片描述

    关键代码

    // 引入element-plus提供的hooks函数
    import { useFormItem } from 'element-plus'
    
    // 通过该函数,可以获取组件当前所在的表单项formItem
    const { fromItem } = useFormItem()
    
    // 在需要的地方,手动触发该表单项的校验
    formItem?.validate('').catch((err) => console.log(err))
    

    这样我们就可以在组件中完成校验了,不需要在外部额外写清除校验的代码了。

    纸上得来终觉浅,绝知此事要躬行。

  • 相关阅读:
    Node.js中的异步API
    dpdk 程序如何配置网卡收发包队列描述符配置?
    常用TS总结
    Docker Nginx容器部署vue项目
    js对象和原型、原型链的关系
    ViT结构详解(pytorch代码)
    论文查重的时候一定要注意格式和内容
    MySQL迁移表分区【图文教程】
    Hadoop3教程(二十二):Yarn的基础架构与工作流程
    Retelling|Facebook1
  • 原文地址:https://blog.csdn.net/ZHANGYANG_1109/article/details/139720224