移动端OTP输入框焦点无法自动跳转,桌面端功能正常的技术问题
移动端OTP输入框焦点无法跳转的问题修复
你的OTP输入逻辑在桌面端正常,但移动端失效,核心问题是移动端虚拟键盘的事件行为和桌面端存在差异,原代码依赖的keydown事件判断在移动端不生效,导致焦点切换逻辑没触发。
问题根源
- 移动端虚拟键盘输入数字时,
keydown事件的e.key值可能不是预期的数字字符(比如部分键盘会返回Unidentified),导致数字判断逻辑跳过。 setTimeout的10ms延迟在移动端可能被系统优先级打断,焦点切换指令失效。- 原HTML的
type="text"会让移动端弹出全键盘,不仅体验差,还会增加事件处理的不确定性。
修复方案
修改代码,改用更适配移动端的事件监听方式,并优化输入框类型:
第一步:调整HTML输入框属性
把输入框类型改为tel并添加inputmode="numeric",确保移动端弹出数字键盘,同时让事件处理更稳定:
<div class="d-flex flex-row"> <input class="form-control login_form_control otp" type="tel" maxlength="1" inputmode="numeric"> <input class="form-control login_form_control otp" type="tel" maxlength="1" inputmode="numeric"> <input class="form-control login_form_control otp" type="tel" maxlength="1" inputmode="numeric"> <input class="form-control login_form_control otp" type="tel" maxlength="1" inputmode="numeric"> <input class="form-control login_form_control otp" type="tel" maxlength="1" inputmode="numeric"> <input class="form-control login_form_control otp" type="tel" maxlength="1" inputmode="numeric"> </div>
第二步:重写JS逻辑
用input事件监听数字输入(移动端更可靠),单独处理退格的keydown事件:
const codes = document.querySelectorAll('.otp') codes[0].focus() codes.forEach((code, idx) => { // 处理数字输入后跳转下一个框 code.addEventListener('input', () => { // 过滤非数字字符,确保输入合法性 code.value = code.value.replace(/[^0-9]/g, '') // 如果当前框有内容且不是最后一个,跳转到下一个 if (code.value && idx < codes.length - 1) { codes[idx + 1].focus() } }) // 处理退格回到上一个框 code.addEventListener('keydown', (e) => { // 只有当前框为空时,退格才跳转到上一个框 if (e.key === 'Backspace' && !code.value && idx > 0) { codes[idx - 1].focus() // 可选:清空上一个框的内容,方便重新输入 codes[idx - 1].value = '' } }) })
关键优化点
input事件:直接监听输入内容变化,不受虚拟键盘的key值差异影响,适配所有移动端场景。- 数字过滤:确保输入框只能接收数字,避免非法字符干扰逻辑。
- 退格逻辑优化:只有当前框为空时才跳转,避免重复触发焦点切换。
- 去掉不必要的
setTimeout:input事件触发时内容已稳定,直接切换焦点更可靠。
内容的提问来源于stack exchange,提问作者Momin Altamash
相关产品推荐
相关产品推荐

