表单校验时如何同时验证手机号和验证码?

子慧(打工版) 阅读 67

我做登录页,需要用户填手机号和短信验证码。现在用的是 HTML5 的 <input type="tel"> 加 pattern 校验手机号,但验证码是 6 位数字,不知道怎么把两个字段联动起来一起校验。

比如用户改了手机号,之前的验证码就失效了,这时候应该清空验证码输入框并提示。但我试了在手机号的 onchange 里清空验证码,结果表单整体校验还是通过了,因为验证码字段本身格式是对的。这逻辑该怎么处理才对?

const phoneInput = document.getElementById('phone');
const codeInput = document.getElementById('code');

phoneInput.addEventListener('change', () => {
  codeInput.value = '';
  // 但此时如果直接点提交,codeInput 因为空值会触发 required 提示,
  // 可如果用户手动输了个 6 位数,哪怕手机号变了,校验也会过……
});
我来解答 赞 9 收藏
二维码
手机扫码查看
1 条解答
♫淑芳
♫淑芳 Lv1
这个问题其实挺常见的,核心在于你需要让验证码字段感知到"关联的手机号已经变了"。

思路是这样的:

当手机号变化时,你清空了验证码输入框的值,但表单校验不会自动知道这两个字段有关联。你需要手动给验证码字段设置一个"校验失败"的状态,直到用户重新获取并填写验证码。

用 HTML5 的 Constraint Validation API 可以做到,核心方法是 setCustomValidity

完整实现:

const phoneInput = document.getElementById('phone');
const codeInput = document.getElementById('code');

// 手机号变化时,清空验证码并标记为"待验证"状态
phoneInput.addEventListener('change', () => {
codeInput.value = '';
// 设置自定义错误,这样即使用户手动输入了6位数字,
// 表单校验也会失败,因为验证码需要重新获取
codeInput.setCustomValidity('请重新获取验证码');
codeInput.reportValidity(); // 可选:立即显示错误提示
});

// 用户输入验证码时,清除错误状态
codeInput.addEventListener('input', () => {
// 只有当验证码是6位数字时才清除错误
if (/^d{6}$/.test(codeInput.value)) {
codeInput.setCustomValidity('');
}
});

// 表单提交时统一校验
document.getElementById('loginForm').addEventListener('submit', (e) => {
if (!phoneInput.checkValidity() || !codeInput.checkValidity()) {
e.preventDefault();
// 这里可以统一提示,或者让浏览器自动显示
}
});


原理解释:

setCustomValidity('') 是关键。默认情况下,元素的 customValidity 是空字符串,表示校验通过。当你设置一个非空字符串时,浏览器会认为这个字段校验失败,即使格式完全正确也不会通过。

所以流程是:
1. 用户修改手机号 → 触发 change 事件 → 清空验证码 + 设置 customValidity 为"请重新获取验证码"
2. 此时验证码字段状态是"有错误",即使用户手动输入 6 位数字,checkValidity() 也会返回 false
3. 用户重新输入验证码 → 触发 input 事件 → 检测到是 6 位数字 → 清除 customValidity,校验恢复正常

补充一点:

如果你还需要在服务端校验验证码是否匹配(这是必须的,前端校验不够安全),可以在提交时把手机号和验证码一起发给后端验证。前端的校验主要是提升用户体验,真正保证安全还是得靠后端。
点赞
2026-03-18 13:03