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

前言

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

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

  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...

相关推荐
文火冰糖的硅基工坊27 分钟前
[嵌入式系统-146]:五次工业革命对应的机器人形态的演进、主要功能的演进以及操作系统的演进
前端·网络·人工智能·嵌入式硬件·机器人
2401_8370885040 分钟前
ResponseEntity - Spring框架的“标准回复模板“
java·前端·spring
yaoganjili1 小时前
用 Tinymce 打造智能写作
前端
angelQ1 小时前
Vue 3 中 ref 获取 scrollHeight 属性为 undefined 问题定位
前端·javascript
Dontla1 小时前
(临时解决)Chrome调试避免跳入第三方源码(设置Blackbox Scripts、将目录添加到忽略列表、向忽略列表添加脚本)
前端·chrome
我的div丢了肿么办1 小时前
js函数声明和函数表达式的理解
前端·javascript·vue.js
云中雾丽1 小时前
React.forwardRef 实战代码示例
前端
朝歌青年说1 小时前
一个在多年的技术债项目中写出来的miniHMR热更新工具
前端
武天1 小时前
一个项目有多个后端地址,每个后端地址的请求拦截器和响应拦截器都不一样,该怎么封装
vue.js
Moonbit1 小时前
倒计时 2 天|Meetup 议题已公开,Copilot 月卡等你来拿!
前端·后端