今天给大家分享一个ref的使用场景:表单嵌套表单,获取子表单的表单校验结果
需求描述
当前有一个表单填写的页面,当点击提交按钮时,要对页面所有表单项进行非空或其他格式验证,若不通过则 toast 提示第一个未通过校验项
校验方式
项目中通常使用 vee-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表单,子组件可通过点击添加按钮无限添加
分析
我们直接在页面使用 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]]
}
以上方案是我暂时能想到的最佳方案,如有不足,欢迎指正,谢谢大家!