vue同时校验多个表单

  • 最开始的想法是将两个表单绑定同一个ref,这样在调用ref.value.validate()是否可以同时校验两个表单呢?

(1) 修改两个表单同时绑定formARef,点击按钮进行校验:
只有第二个表单进行校验了,这是因为在 Vue3 中,使用 ref 绑定表单元素时,如果你给两个不同的表单元素都绑定了相同的 ref,例如 ref="formRef",那么在访问formRef.value 时,实际上只能引用到最后一个具有相同 ref 的表单元素。这是因为 ref 是唯一标识符,不同的 ref 值对应不同的元素或组件实例。简单理解来说就是第二个组件实例会将第一个组件实例覆盖掉,所以才会造成只有第二个表单进行了校验,而第一个表单无反应的情况。
(2)那么,我们重新将两个表单绑定两个ref,分别为 formARef 和 formBRef。另外一种思路是我们依次校验formA 和 formB,在formA校验通过后再校验formB是否可行呢?
其实是可行的,但是问题也很明显

    1.从开发角度讲,代码嵌套层数过多,如果是表单更多只会更严重,严重影响代码易读性和可维护性。

    2.从用户角度讲,校验不全,当表单A校验不通过时,无法校验表单B,一旦表单过多,用户可能需要多次校验多次修改才可校验通过,十分影响用户体验。

****解决方案 ****
1.使用async await
我们先查看检验返回的结果。

   const checkForm = () => {
      const formValidA = formARef.value.validateField()
      const formValidB = formBRef.value.validateField()
      console.log(formValidA) // Promise <pending>
      console.log(formValidB) // Promise <pending>
   }

通过打印校验的返回结果可以看到返回的是一个pending状态的Promise。这是因为许多表单验证库(如 VeeValidate 或 Element Plus 等)在进行异步验证时会返回 Promise 以便处理异步操作。在这种情况下,validateField方法会返回一个 Promise,而不是直接返回一个布尔值。既然是Promise,我们可以使用async await 去接收Promise返回成功的结果
打印一下,如果校验成功的话,返回的结果为true,如此我们就可以通过判断 true / false 来判断当前的校验结果。但是当校验失败时,控制台会报警告:“Unhandled error during execution of component event handler”,原因是当校验失败是,Promise会抛出异常而又没有被及时捕获所导致,故而,我们用try catch捕获这个异常:

   const checkForm = async () => {
      try {
         const formValidA = await formARef.value.validateField()
         const formValidB = await formBRef.value.validateField()
         if (formValidA && formValidB) {
            /**  
             * 执行校验通过后的逻辑
             * 下一步操作...
             * 发请求...
             * 页面跳转...
             */
         }
      } catch (error) {
         /**
          * 执行校验失败抛出异常的逻辑
          */
      }
   }

由于我这次的页面有5个表单,而表单4、5在表单2某字段值为true时显示,所以在我用了上面方法统一处理几个表单时发现,前3个表单都可以正常返回,而当我把4、5表单写入时,会报错“resource.vue:1173 Uncaught (in promise) TypeError: Cannot read properties of null (reading 'validateField')at comfirmdemand (resource.vue:1173:1)”,因为在在表单2某字段值为false时,表单4、5都没显示,Ref.value.validateField()根本读取不到,所以加上判断条件,当表单2某字段为true时去操作表单4、5:

const demandFormRef1 = ref(null)
const demandFormRef2 = ref(null)
const demandFormRef3 = ref(null)
const demandFormRef4 = ref(null)
const demandFormRef5 = ref(null)
if (demandForm.value.lifting) {
    formName.value = await Promise.all([demandFormRef1.value.validateField(), demandFormRef2.value.validateField(), demandFormRef3.value.validateField(), demandFormRef4.value.validateField(), demandFormRef5.value.validateField()])
  } else {
    formName.value = await Promise.all([demandFormRef1.value.validateField(), demandFormRef2.value.validateField(), demandFormRef3.value.validateField()])
  }

然后,当都为true时,我们进行后面的操作:

if (arr.every(result => result === true)) {
        console.log('校验通过')
//在这里就可以写验证通过时的操作或者调用接口
}

参考文章:https://blog.csdn.net/weixin_66406649/article/details/139685992

posted @ 2024-08-02 15:32  没心没肺没人性  阅读(176)  评论(0编辑  收藏  举报