el-form表单存在异步校验时,如何对表单进行整体校验?

本文揭示了在使用Element UI的el-form组件时,异步校验可能导致的表单提交逻辑错误。当表单包含异步校验规则时,常规的同步校验逻辑无法正确阻拦有误的表单提交。文章提供了两种解决方案:一是将表单提交逻辑置于validate方法的回调函数内;二是利用async/await与try/catch进行表单校验。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在项目中如果使用了element-ui的话,在需要实现表单功能的时候,肯定会使用到element-ui的el-form表单来编程。

前序:

首先,我们先来看一下el-form的官方文档介绍: 

方法名说明参数
validate对整个表单进行校验的方法,参数为一个回调函数。该回调函数会在校验结束后被调用,并传入两个参数:是否校验成功和未通过校验的字段。若不传入回调函数,则会返回一个 promiseFunction(callback: Function(boolean, object))

标红的这两句话很重要。

隐患:

既然有了官方提供的方法,那么在提交表单前,再使用validate方法,对表单进行一个整体校验即可,然后我们可能会使用以下写法:

let hasError = false; //表单是否有报错的标志

//表单校验逻辑
this.$refs['ruleForm'].validate((valid) => {
    if (valid) {
        //表单有报错,将hasError置为true
        hasError = true;
    }
});

//如果表单有报错,return,阻止 表单提交
if(hasError){
    return
}

//下方是校验通过后,表单提交的逻辑
//xxxxxxx

↑↑↑↑很多同学校验表单的逻辑时,可能就会像上面这种写法,先调用el-form的validate方法,在回调函数中通过valid来判断表单是否有报错,在调用完validate方法之后判断表单是否有报错来阻止表单提交。

这种写法是存在“安全隐患”的:

  1. 在el-form的rules字段校验规则中没有异步校验的情况下,上述代码是同步执行的,在调用完validate方法之后是可以正确拿到hasError,这种情况下这样写没问题。
  2. 但是如果el-form的rules字段校验规则中存在异步校验(最下面有解释)的情况,那么validate中的回调函数就是异步执行的,这时无论表单有没有报错都会走提交表单的逻辑↓↓↓↓↓        
let hasError = false; //表单是否有报错的标志

//表单校验逻辑(存在异步校验)
this.$refs['ruleForm'].validate((valid) => {
    if (valid) {
         
        //异步校验,异步执行,会在下面的代码if(hasError)之后执行,才能拿到异步执行的结果(正确的hasError的值)

        //表单有报错,将hasError置为true
        hasError = true;
    }
});

//如果表单有报错,return,阻止 表单提交(这里是同步执行的代码,会先执行这句,然而hasError在这一步永远是false)
if(hasError){
    return
}

//下方是校验通过后,表单提交的逻辑
//xxxxxxx

解决:

方式一:将表单提交逻辑直接放到回调函数中

如果觉得表单提交逻辑太多就单独写一个函数在回调函数里面调用。


//表单校验逻辑(存在异步校验)
this.$refs['ruleForm'].validate((valid) => {
    
    if (!valid) {
         //表单校验有报错,return,代码不再往下执行
         return
    }
    
    //表单提交校验写到回调函数内
    //表单校验通过,进入表单提交逻辑
    //xxxxxxx

});

方式二:使用async/await和try catch组合来进行表单校验

官方说明:如果validate方法不传入回调函数,则会返回一个 promise。表单校验没有报错则在validate内部执行resolve(valid),失败则执行reject(valid) (这块具体内部实现看el-form源码)。这样可以使用async/await和try catch组合来进行表单校验

async submitForm() {
    try {
      //调用表单的validate方法,执行表单校验
      await this.$refs['ruleForm'].validate()
    }catch(e) {
      //如果表单有报错,则进入catch,此时直接return不执行表单提交
      return
    }

    //表单校验通过,进入表单提交逻辑
    //xxxxxxx
}

补充:什么是异步校验?

有些场景的表单字段,需要调用接口,把某个input框的输入值传给服务端进行校验,服务端校验完成后把校验结果返回,这种情况就属于是异步校验。

el-form的整体表单校验validate函数是等所有表单字段(包括异步校验的字段)都校验完成才执行validate中的回调函数,这就会存在我前面说的“安全隐患”。

例:

 <el-form-item label="名称:" prop="name">
    <el-input
          v-model.trim="formDetail.name"
          placeholder="1-20个字符"   
     />
</el-form-item>

data() {
    //校验规则
    formRules = {
        //name字段需要进行异步校验
        name: [
             validator: (rule, val, cb) => {
                  //发送ajax到服务端进行校验
                  this.$http({
                      url: "/service/ajax-checkname",
                      method: "get",
                      data: {
                          name: val
                      }
                  }).then(res => {
                      let result = res.data;
                      if (!result.status) {
                         cb(result.message); //校验不通过,报错
                      } else {
                         cb(); //校验通过
                      }
                 });
            },
            trigger: "blur"
        ]
    }
}

灵活好用的jq表单验证,自己封装可按照验证需求添加验证方法,不需要修改验证整体结构,内含使用说明。 var arr = new Array(); /* */ //用户验证 arr[0] = new XQValidation(); arr[0].XChecksetcont("3-12长度,字母,数字,下划线", "", "表单不能为空", "验证失败", "此用户已存在", "此用户可以注册"); arr[0].posturl("/FormValidation/ajax/ajax-validation.asmx/user_isNull", "name"); arr[0].check("tname", "td1", "checkusername", true, true); //密码验证 arr[1] = new XQValidation(); arr[1].XChecksetcont("6-20长度,字母,数字,和其他符号", "ok", "表单不能为空", "wrong", "表单不能为空"); arr[1].check("tpass", "td2", "checkpassword", true, false); //邮箱验证 arr[2] = new XQValidation(); arr[2].XChecksetcont("正确邮箱", "ok", "表单不能为空", "wrong"); arr[2].check("tmail", "td3", "checkemail", true, false); //联系方式验证 arr[3] = new XQValidation(); arr[3].XChecksetcont("正确手机,非必须", "ok", "表单不能为空", "wrong"); arr[3].check("tmobile", "td4", "checkcontactway", true, false); //QQ验证 arr[4] = new XQValidation(); arr[4].XChecksetcont("qq,非必须", "ok", "表单不能为空", "wrong"); arr[4].check("tqq", "td5", "checkqq", false, false); //验证码验证 arr[5] = new XQValidation(); arr[5].XChecksetcont("", "ok", "表单不能为空", "wrong"); arr[5].check("tcode", "td6", "checknull", true, false); //重复密码验证 arr[6] = new XQValidation(); arr[6].XChecksetcont("", "", "表单不能为空", "密码不匹配"); arr[6].check("tapass", "td7", "checkpassword_", true, false); /* *summary:提交表单验证 */ function formok() { for (var i = 0; i < arr.length; i++) {//循环遍历验证对象 if (!arr[i].getstate()) { arr[i].alertwrong(); return false } } //判断两次输入的密码是否一样 if (!chkapass($("tapass").value)) { arr[6].alertwrong(); return false; } return true; }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值