炽热之痛:解读vant表单校验失败

前言

  • 常网IT戳我呀!
  • 常网IT源码上线啦!
  • 本篇录入vue专栏,希望能祝君拿下Offer一臂之力,各位看官感兴趣可移步🚶。
  • 有人说面试造火箭,进去拧螺丝;其实个人觉得问的问题是项目中涉及的点 || 热门的技术栈都是很好的面试体验,不要是旁门左道冷门的知识,实际上并不会用到的。
  • 接下来想分享一些自己在项目中遇到的场景。

如果你错过了落日余晖,请记得还有漫天星辰。

我的意思是:愿你历经山河,仍觉人间值得。

炽热之痛:解读vant表单校验失败

一、问题剖析

那是一个风和日丽的早上,我想要去看漫天霞光。

要和心上人手挽手走在街上,

清晨的花香,傍晚的夕阳。

正当我沉迷于甜蜜的幻想中,实习生小白喊道:师傅师傅,我遇到一个问题,帮我看看呗!

真是的,慌慌张张的,说吧~

问题是这样子的:

在页面中,有一个vant-form表单组件,有:

  • 字段A,类型单选框,必填
  • 若单选框选为true,则显示字段B(必填)
  • 若单选框为false,则不显示字段B(必填)
  • 字段C,必填

二、现状

正常现象

字段A、C都选为,提交正常。

有问题

我先选择了字段A单选框为true,这时字段B显示;

我单选框切换为false,字段B隐藏;

字段C

此时提交表单时,发现校验失败。

提示字段C是必填,可我明明已经填了。

三、分析

为什么字段A、C都选为否,提交正常;

字段A从true,换到false,就字段C校验失败呢?

校验方法:

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校验失败,此时在二次校验就成功了。

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必填,但是我填了,还是提示我未填

可能是由于以下原因导致的:

  1. 校验规则配置错误:确保 :rules 属性绑定到正确的校验规则数组,并且每个规则都正确地声明了必填规则,如 required: true。
  2. 数据绑定问题:确认表单项的 v-model 是否与表单数据进行正确的双向绑定。确保你在组件实例中定义了对应的表单数据属性,并将其与表单项的 v-model 进行绑定。
  3. 视图更新问题:如果在填写表单后仍然提示未填,可能是因为视图没有及时更新。可以尝试手动触发一次视图更新,例如通过调用 $forceUpdate() 或者在更新后重新获取焦点等方式来刷新视图。

但排查了都没有问题。

五、vant-form的validate()原理

既然都讲到这里了,顺便跟你说一下validate()原理吧。

van-form 的 validate() 方法用于触发表单的校验。当调用 validate() 方法时,van-form 组件会按照配置的校验规则对所有表单项进行逐一校验,并返回一个 Promise。

van-form 的 validate() 方法的原理如下:

  1. 遍历所有表单项:validate() 方法会遍历 van-form 组件的所有子组件,找到包含 rules 属性的表单项组件。这些组件可以是 van-field、van-checkbox-group、van-radio-group 等。
  2. 校验表单项:对于每个需要校验的表单项,validate() 方法会获取该表单项的值,并遍历其关联的校验规则。
  3. 执行校验规则:对于每个校验规则,validate() 方法会根据规则类型进行相应的校验。常见的校验规则类型包括 required(必填)、min(最小值)、max(最大值)、pattern(正则表达式)等。
  4. 校验结果处理:如果校验失败,将为校验不通过的表单项设置错误提示信息;如果校验成功,将清除该表单项的错误提示信息。
  5. 返回校验结果:validate() 方法会返回一个 Promise,该 Promise 的 resolve 值是一个对象,包含两个属性:valid 表示整个表单的校验结果(true为校验通过,false为校验不通过),errors 表示每个校验不通过的表单项及其错误提示信息。

后记

我想,表单校验是我们开发中很常见的场景,至于说达到某种条件,让某个数据项隐藏,如果用v-if或许皆大欢喜,可能是性能上的开销。

如果用的是v-show,那可要注意校验的问题。

在解决方案中已回答。

如果有其他更好的方法也欢迎评论区见,这里提供的只是诸多方法之一。

我是Dignity_呱,来交个朋友呀,有朋自远方来,不亦乐乎呀!深夜末班车

👍 如果对您有帮助,您的点赞是我前进的润滑剂。

以往推荐

靓仔,说一下keep-alive缓存组件后怎么更新及原理?

面试官问我watch和computed的区别以及选择?

面试官问我new Vue阶段做了什么?

前端仔,快把dist部署到Nginx上

多图详解,一次性啃懂原型链(上万字)

Vue-Cli3搭建组件库

Vue实现动态路由(和面试官吹项目亮点)

项目中你不知道的Axios骚操作(手写核心原理、兼容性)

VuePress搭建项目组件文档

原文链接

juejin.cn/spost/73382…

原文链接:https://juejin.cn/post/7338296953845776436 作者:Dignity_呱

(0)
上一篇 2024年2月22日 下午5:14
下一篇 2024年2月23日 上午10:05

相关推荐

发表回复

登录后才能评论