验证码校验不能用pattern或required,因其仅校验格式或非空,无法验证一次性、有时效、需服务端比对的业务语义;必须由后端生成下发并校验,前端只负责传值、防抖与状态同步。

HTML 表单里没有原生的「验证码」控件,所谓“验证码校验”本质上是前端配合后端完成的一次性 token 验证,不是 required 或 pattern 能覆盖的场景。它必须由服务端生成、下发、比对,前端只负责传递和基础防误操作。
为什么不能用 pattern 或 type="text" + required 做验证码校验
验证码(如 4 位图形码、滑块结果、短信口令)的核心特征是:一次性、有时效、与用户行为强绑定。浏览器原生验证属性完全不感知这些语义:
-
pattern只校验字符串格式(比如是否为 4 位数字),但无法判断该值是否「当前有效」——上一秒有效的验证码,下一秒可能已过期或被使用 -
required只检查是否为空,填了任意 4 位数(哪怕是错的)就通过,毫无业务意义 - 所有原生属性都在客户端执行,可被绕过;而验证码存在的根本目的就是对抗自动化提交,必须依赖服务端决策
前端该做哪些事:传值 + 防抖 + 状态同步
前端不是甩手掌柜,而是要精准配合后端接口,重点在「不传错、不重复、不卡住」:
- 验证码输入框必须有
name属性(如name="captcha"),确保能随表单一起提交;不要用id代替 - 提交前手动调用
checkValidity()没用,但可以加一层轻量级前置判断:比如长度不足 4 位、含非数字字符(针对数字型验证码),用input.value.replace(/\D/g, '').length !== 4快速拦截明显错误 - 点击「获取验证码」按钮后,必须禁用按钮并倒计时,防止用户连点触发多次发送;倒计时结束前禁止再次提交表单(可用
form.setAttribute('novalidate', '')临时关闭原生校验,避免干扰) - 服务端返回错误(如
{"code": 400, "msg": "验证码已失效"})后,要清空输入框,并调用input.setCustomValidity("验证码已失效"),再立刻跟一句input.reportValidity()强制显示提示(否则用户看不到反馈)
最容易被忽略的三个坑
验证码逻辑崩掉,往往不是后端出问题,而是前端状态没管住:
- 用户输入正确验证码并提交成功后,**没清空输入框** → 下次刷新页面或重进表单时,残留值可能被误提交,后端判定为「重复使用」
- 验证码图片点击刷新时,只换了图片 URL,但没重置
input.setCustomValidity("")→ 旧错误状态残留,checkValidity()一直返回false,表单永远无法提交 - 用 AJAX 提交表单但没阻止默认行为 → 浏览器仍会走原生 submit 流程,导致验证码被发两遍,后端拒绝第二次请求
真正关键的校验动作永远发生在服务端响应之后;前端唯一可控的,是让这个过程不卡、不糊、不误导用户。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











