需求
在Vue 2
项目中,由于一个页面存在多个的表单,如下代码:
<template>
<div>
<el-form ref="form1" :rules="rules1">
<!-- 表单内容 -->
</el-form>
<el-form ref="form2" :rules="rules2">
<!-- 表单内容 -->
</el-form>
<el-button @click="submit">提交</el-button>
</div>
</template>
然后,在对这些表单进行校验的时候可能会导致回调地狱
,如下代码:
submit(){
this.$refs.form1.validate(valid1=>{
if(valid1){
this.$refs.form2.validate(valid2=>{
if(valid2) {
//...
}
})
}
})
}
解决思路
首先,我看了下别人的思路,但和我想要的效果不大一样,而关于回调地狱
的解决方案自然就是Promise.all()
的方式了。
submit(){
Promise.all([
new Promise(resolve => this.$refs.form1.validate(v=>resolve(v))),
new Promise(resolve => this.$refs.form2.validate(v=>resolve(v)))
]).then(([v1, v2]) => {
console.debug(v1 , v2);
//v1 , v2返回Boolean值
if (v1 && v2) {
//...
}
})
}
这么做从代码量上来说可能没有别人的精简,但是至少我能知道每个表单的校验结果(v1, v2),也能满足校验多个表单的目的。当然还有其它几种写法详见扩展。
扩展
this.$refs.form1.validate()
在没有加callback的时后返回的就是一个Promise对象,并且如果直接在Promise.all
里面放this.$refs.form1.validate()
时,一但校验不通过控制台就会出现错误日志(Uncaught (in promise)),原因是没有对异常做处理。所以也就有另一种写法:
submit(){
Promise.all([
this.$refs.form1.validate().then(v=>v,()=>false),
//在then中处理异常,返回false
this.$refs.form2.validate().then(v=>v,()=>false)
]).then(([v1, v2]) => {
//v1 , v2为Boolean值
console.debug(v1 , v2);
if (v1 && v2) {
//...
}
})
}
最后,如果想要在校验失败的时候,然会具体的校验失败信息还能这么写:
submit(){
Promise.all([
this.$refs.form1.validate().then(v=>v,e=>e),
//在then中处理异常,返回对象
this.$refs.form2.validate().then(v=>v,e=>e)
]).then(([v1, v2]) => {
//v1 , v2为Boolean值或者对象
console.debug(v1 , v2);
//这时候假设form1校验失败,那么v1返回的就是一个对象,就像这样:
//"username": [{"message": "请输入用户名称","field": "username"}]}
if (v1 && v2) {
//...
}
})
}
或者这么写:
submit(){
Promise.all([
this.$refs.form1.validate(),
this.$refs.form2.validate()
]).then(() => {
//这时候的then就无所谓传进来的值了,因为只有两个都校验通过才会到这个地方来
//...
}).catch(e=>{
console.debug(e)
//但凡有一个校验失败就会进入到这里,e无法甄别是来自哪个form,如果需要可以在validate().catch中加入可以甄别的值以便判断,这里就展开了
//...
})
}