
本文详解为何otp输入框的change事件无法触发自动聚焦,以及如何通过input或keyup事件正确实现数字输入后自动跳转到下一输入框的功能。
在构建6位一次性密码(OTP)输入组件时,一个常见需求是:用户在某个输入框中输入一位数字后,焦点自动移至下一个输入框。许多开发者会尝试使用 change 事件来监听值变更并调用 focus(),但会发现该逻辑在实际操作中并不生效——控制台可能打印出日志,但焦点却未成功切换。
根本原因在于:change 事件并非实时触发。根据 HTML 规范,change 仅在输入框失去焦点(blur)且其值发生过修改时才触发。这意味着,当用户刚输入一个数字、尚未离开当前输入框时,change 根本不会被派发,自然也无法执行后续的 focus() 操作。
✅ 正确做法是改用 input 事件(推荐)或 keyup 事件:
- input 事件在每次输入值变化时立即触发(包括粘贴、删除、输入等所有场景),语义准确、兼容性好(IE9+);
- keyup 事件则在按键抬起时触发,适合需要精确捕获键盘行为的场景,但不响应鼠标粘贴等非键盘输入。
以下是优化后的核心代码示例(已修复原逻辑中的多个隐患):
const OTP_LENGTH = 6;
const textInputs = [];
const otpContainer = document.getElementById('otp-container');
for (let i = 0; i < OTP_LENGTH; i++) {
const input = document.createElement('input');
input.type = 'text'; // 注意:type="number" 在移动端可能引发键盘兼容性问题,建议用 text + pattern/regex 校验
input.maxLength = 1; // 使用 maxLength 属性(非 max-length)
input.id = `otp-input-${i}`; // 避免重复 ID(原代码中所有 input id 均为 'otp-input',违反唯一性)
input.dataset.otpPos = i;
input.classList.add('otp-input');
// 关键:监听 input 事件而非 change
input.addEventListener('input', function (e) {
const target = e.target;
const position = parseInt(target.dataset.otpPos, 10);
// 清除非数字字符(可选增强)
target.value = target.value.replace(/[^0-9]/g, '');
// 若输入有效数字且未到末位,则聚焦下一个
if (target.value && position < OTP_LENGTH - 1) {
const nextInput = textInputs[position + 1];
if (nextInput) {
nextInput.focus();
}
}
});
// 可选:支持退格键回退(提升体验)
input.addEventListener('keydown', function (e) {
if (e.key === 'Backspace' && !this.value && this.previousElementSibling) {
this.previousElementSibling.focus();
}
});
textInputs.push(input);
otpContainer.appendChild(input);
}
// 补充:首输入框自动聚焦(提升可用性)
if (textInputs[0]) textInputs[0].focus();⚠️ 注意事项:
- 避免重复 ID:HTML 中 id 必须唯一,原代码中所有输入框 id="otp-input" 会导致 document.getElementById 行为不可预测;
- 慎用 type="number":在 iOS Safari 和部分安卓浏览器中,type="number" 可能导致输入延迟、光标错位或无法触发 input 事件,生产环境建议统一用 type="text" 并配合 inputmode="numeric" 和正则校验;
- 防止无限 focus 循环:确保 nextInput.focus() 前已将当前输入框 blur(现代浏览器通常自动处理,但显式调用 target.blur() 更稳妥);
- 移动端适配:添加 inputmode="numeric" 和 pattern="[0-9]*" 可唤起数字键盘,提升用户体验。
总结:OTP 自动聚焦失败的核心症结在于事件选型错误。牢记 change ≠ input,优先选用 input 事件实现响应式焦点流转,并辅以良好的输入控制与无障碍支持,即可构建稳定、跨端兼容的 OTP 输入体验。










