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

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

前序:

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

方法名 说明 参数
validate 对整个表单进行校验的方法,参数为一个回调函数。该回调函数会在校验结束后被调用,并传入两个参数:是否校验成功和未通过校验的字段。若不传入回调函数,则会返回一个 promise Function(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框的输入值传给服务端进行校验,服务端校验完成后把校验结果返回,这种情况就属于是异步校验。

扫描二维码关注公众号,回复: 17064957 查看本文章

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"
        ]
    }
}

猜你喜欢

转载自blog.csdn.net/weixin_46422035/article/details/125596836