单个文本框无法可靠支持验证码场景,需多个独立 maxlength="1" 的 input 并排组合;必须同时设置 inputmode="numeric" 和 pattern="[0-9]*" 并配合 js 实时清洗、paste/keydown/input 事件监听及隐藏域同步。

为什么不能只用一个 <input>
单个 <input type="text"> 无法可靠支持验证码场景下的光标定位、逐位删除、粘贴截断和视觉对齐。用户粘贴“1234”时会全塞进一个框,按一次 Backspace 会清空全部而非仅当前位;iOS 上还可能弹出全键盘而非数字键盘。真正可控的结构是多个独立 <input maxlength="1"> 元素并排组合。
inputmode="numeric" 和 pattern="[0-9]*" 必须同时加
只设 inputmode="numeric" 在部分 Android/Chrome 有效,但 iOS Safari 常忽略它;只设 pattern="[0-9]*" 又不能阻止非数字粘贴。两者配合才能在多数机型上唤起纯数字键盘,并为后续 JS 清洗留余地:
-
inputmode="numeric"告诉浏览器“预期输入数字”,影响软键盘类型 -
pattern="[0-9]*"是表单验证属性,iOS Safari 会据此强制数字键盘(注意不是type="number",后者有上下箭头且不触发input事件) - 仍需 JS 监听
input事件做实时清洗:e.target.value = e.target.value.replace(/\D/g, '')
粘贴时必须拦截 paste 事件并手动分发
默认粘贴行为会把整段文本塞进当前焦点框,60% 的失败都源于没接管这个环节。关键动作三步走:
- 给每个
<input>绑定paste事件,第一时间调用e.preventDefault() - 取
e.clipboardData?.getData('text')?.replace(/\D/g, ''),过滤掉所有非数字字符 - 从当前 input 开始,按顺序赋值:比如粘贴 “123456” 到 4 位框,只取前 4 位,
inputs[i].value = cleaned[i] || '';填完最后一个后调用inputs[inputs.length - 1].focus()或blur()防止继续输入
自动跳格逻辑要区分 input 和 keydown 场景
只监听 input 事件不够——退格、方向键、粘贴后回删都需要 keydown 补充控制:
-
input事件里判断:if (e.target.value) nextInput?.focus() -
keydown里处理Backspace/Delete:if (!e.target.value && e.target.previousElementSibling) { e.preventDefault(); e.target.previousElementSibling.focus(); } - 方向键也要接管:
ArrowLeft和ArrowRight时手动focus()相邻 input,避免浏览器默认行为导致焦点跳到页面其他元素 - 所有 input 应同步写入一个隐藏的
<input type="hidden">,供表单提交或校验使用
最容易被忽略的是 iOS autofocus 静默失败和粘贴后未触发 input 事件。不要在页面加载时直接 focus(),等用户点击「获取验证码」后再执行;粘贴后记得手动 dispatchEvent(new Event('input', { bubbles: true })),否则依赖 input 事件的验证逻辑会收不到更新。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











