前言
- 常网IT戳我呀!
- 常网IT源码上线啦!
- 本篇录入vue专栏,希望能祝君拿下Offer一臂之力,各位看官感兴趣可移步🚶。
- 有人说面试造火箭,进去拧螺丝;其实个人觉得问的问题是项目中涉及的点 || 热门的技术栈都是很好的面试体验,不要是旁门左道冷门的知识,实际上并不会用到的。
- 接下来想分享一些自己在项目中遇到的场景。
如果你错过了落日余晖,请记得还有漫天星辰。
我的意思是:愿你历经山河,仍觉人间值得。
一、问题剖析
那是一个风和日丽的早上,我想要去看漫天霞光。
要和心上人手挽手走在街上,
清晨的花香,傍晚的夕阳。
正当我沉迷于甜蜜的幻想中,实习生小白喊道:师傅师傅,我遇到一个问题,帮我看看呗!
真是的,慌慌张张的,说吧~
问题是这样子的:
在页面中,有一个vant-form表单组件,有:
- 字段
A
,类型单选框,必填 - 若单选框选为true,则显示字段
B
(必填) - 若单选框为false,则不显示字段
B
(必填) - 字段
C
,必填
二、现状
正常现象
字段A、C
都选为否,提交正常。
有问题
我先选择了字段A单选框为true,这时字段B显示;
我单选框切换为false,字段B隐藏;
字段C
此时提交表单时,发现校验失败。
提示字段C
是必填,可我明明已经填了。
三、分析
为什么字段A、C都选为否,提交正常;
字段A从true,换到false,就字段C校验失败呢?
校验方法:
javascript
await (this.$refs.formData).validate().then(res => {
console.log(res, '效验成功')
}).catch(async res => {
console.log(res, '校验失败')
// 做个小优化,失败后,自动滚动到第一条校验失败的字段的位置
this.$refs.formData.scrollToField(res[0].name, true)
})
猜想:大概率是因为字段A,选true,会让字段B显示;然后又切回false,让字段B隐藏。
虽然页面中已经隐藏字段B了,但其实校验可能还是会校验到,就DOM没更新,但我使用nextTick的时候仍然不行。
四、解决方案
4.1 key + 二次校验法
于是我尝试在form表单组件加上key,点击提交按钮的时候更新其key,相当于刷新一下组件。
刷新完之后,还是会进catch校验失败,此时在二次校验就成功了。
javascript
this.renderKey += 1 // 刷新表单
await (this.$refs.formData).validate().then(res => {
console.log(res, '效验成功')
}).catch(async res => {
console.log(res, '校验失败')
// 二次校验
await (this.$refs.formData).validate().then(res => {
console.log(res, '效验成功')
}).catch(async res => {
console.log(res, '校验失败')
})
})
这个页面的组件嵌套太深,老项目来着,所以可能才导致此问题。
尽管用 this.$forceUpdate()
强制性刷新也无效。
4.2 手动校验
在校验失败catch的时候,e返回的是[字段C],校验失败的结果集,我获取form表单list的数据,拿catch的校验失败的集合去看看form表单的list的value有没有值,如果有值,我手动给他改为校验成功。
清空校验:this.$refs.formData.resetValidation();
其实应该是要解决为什么会校验rule有问题,明明填了,上面两种有点取巧。
van-form的表单,我设置了rule必填,但是我填了,还是提示我未填
可能是由于以下原因导致的:
- 校验规则配置错误:确保 :rules 属性绑定到正确的校验规则数组,并且每个规则都正确地声明了必填规则,如 required: true。
- 数据绑定问题:确认表单项的 v-model 是否与表单数据进行正确的双向绑定。确保你在组件实例中定义了对应的表单数据属性,并将其与表单项的 v-model 进行绑定。
- 视图更新问题:如果在填写表单后仍然提示未填,可能是因为视图没有及时更新。可以尝试手动触发一次视图更新,例如通过调用 $forceUpdate() 或者在更新后重新获取焦点等方式来刷新视图。
但排查了都没有问题。
五、vant-form的validate()原理
既然都讲到这里了,顺便跟你说一下validate()原理吧。
van-form 的 validate() 方法用于触发表单的校验。当调用 validate() 方法时,van-form 组件会按照配置的校验规则对所有表单项进行逐一校验,并返回一个 Promise。
van-form 的 validate() 方法的原理如下:
- 遍历所有表单项:validate() 方法会遍历 van-form 组件的所有子组件,找到包含 rules 属性的表单项组件。这些组件可以是 van-field、van-checkbox-group、van-radio-group 等。
- 校验表单项:对于每个需要校验的表单项,validate() 方法会获取该表单项的值,并遍历其关联的校验规则。
- 执行校验规则:对于每个校验规则,validate() 方法会根据规则类型进行相应的校验。常见的校验规则类型包括 required(必填)、min(最小值)、max(最大值)、pattern(正则表达式)等。
- 校验结果处理:如果校验失败,将为校验不通过的表单项设置错误提示信息;如果校验成功,将清除该表单项的错误提示信息。
- 返回校验结果:validate() 方法会返回一个 Promise,该 Promise 的 resolve 值是一个对象,包含两个属性:valid 表示整个表单的校验结果(true为校验通过,false为校验不通过),errors 表示每个校验不通过的表单项及其错误提示信息。
后记
我想,表单校验是我们开发中很常见的场景,至于说达到某种条件,让某个数据项隐藏,如果用v-if或许皆大欢喜,可能是性能上的开销。
如果用的是v-show,那可要注意校验的问题。
在解决方案中已回答。
如果有其他更好的方法也欢迎评论区见,这里提供的只是诸多方法之一。
我是Dignity_呱,来交个朋友呀,有朋自远方来,不亦乐乎呀!深夜末班车
👍 如果对您有帮助,您的点赞是我前进的润滑剂。