ref的妙用——表单嵌套校验

415 阅读1分钟

今天给大家分享一个ref的使用场景:表单嵌套表单,获取子表单的表单校验结果

需求描述

当前有一个表单填写的页面,当点击提交按钮时,要对页面所有表单项进行非空或其他格式验证,若不通过则 toast 提示第一个未通过校验项

校验方式

项目中通常使用 vee-validate 自定义校验规则,我们可以通过 this.validator.validate()方法对表单进行校验,通过this.validator.validate()方法对表单进行校验,通过this.validator.errors.all()[0] 获取校验未通过的第一项,关于如何自定义规则的文章较多,就不一一赘述

//点击下一步
next(){
  this.$validator.validate().then(valid=>{
    if(valid){
      //校验成功
    } else {
      //toast提示
      this.toast(this.$validator.errors.all()[0])
    }
  })
}cath(err=>{console.log(err)})

页面结构

由vant ui构成的一个表单,包含一个子组件,子组件也是一个vant表单,子组件可通过点击添加按钮无限添加

4B548A5F-DD0F-4662-BB95-9A002A80FBBF.png

分析

我们直接在页面使用 this.validator.validate()方法对页面表单进行校验,只能得到父组件的表单项校验结果,无法对子组件表单项进行校验,此时我们就需要通过this.validator.validate() 方法对页面表单进行校验,只能得到父组件的表单项校验结果,无法对子组件表单项进行校验,此时我们就需要通过this.ref来解决这个问题

//父组件
//html部分
<div>
  //......
  //父组件表单项
  //由于某些原因,子组件接受的是一个对象,非数组 
  <div v-for="(item,index) in list" :key="index">
    <Child ref="childInfo" :info="item">
  </div>
  //.....
</div>
//js部分 表单验证
next(){
  this.$validator.validate().then(async valid=>{
  if(valid){
    //父组件表单验证成功
    //子组件表单验证 由于子组件非单个,需循环拿到每一个,再者isValidate是异步的,因此只能用for循环
    for (let i = 0; i < this.list.length; i++) {
      let [flag, message] = await this.$refs.childInfo[i].isValidate()
      if (!flag) {
        return this.$toast(message)
   }
    //若子组件为单个表单 子组件设置ref为childInfo
    // let [flag, message] = await this.$refs.childInfo.isValidate()
    //   if (!flag) {
    //     return this.$toast(message)
    // }
  } else {
    this.$toast(this.$validator.errors.all()[0])
  }
}).catch(err=> consle.log(err))
}
//子组件 js部分 表单验证
async isValidate() {
  let res = await this.$validator.validate()
  if (res) {
     return [true, null]
  }
  return [false, this.$validator.errors.all()[0]]
 }

以上方案是我暂时能想到的最佳方案,如有不足,欢迎指正,谢谢大家!