应使用 u-code-input 或 uv-code-input 组件,避免手写六个 input 标签循环渲染,因其在 H5 删除键失效、iOS 微信光标错位、nvue 键盘不弹出等兼容性问题突出。

直接用 u-code-input 或 uv-code-input,别手写六个 input 标签循环渲染——后者在 H5 端删除键失效、iOS 微信里光标错位、nvue 下键盘不弹出,是已知的兼容性雷区。
为什么六个 input + v-for 方案在 H5 上删除键没反应
根本原因是浏览器对空 input 元素触发 input 事件的逻辑:当光标停在第 3 个空格子上按退格,值没变(仍是空字符串),@input 不触发,也就没法通知上一个格子清空或回退焦点。很多实现靠 @keydown.delete 拦截,但这个事件在部分 Android 浏览器里不冒泡,在 iOS Safari 里甚至不触发。
更麻烦的是焦点管理:setTimeout(() => this.$refs.input[i].focus(), 0) 这类“卡时机”写法,在不同机型上表现不一致,快了没 focus 成,慢了导致两次 focus 闪烁。
- 不要依赖
codes[index]的数组索引推导当前输入位置——用户可能点击第 5 格再删第 2 格,顺序逻辑直接崩 - 不要给每个
input设type="number"后还加maxlength="1"——H5 下部分浏览器会阻止粘贴整串数字 - 避免用
adjust-position="false"+auto-blur="true"组合——在微信小程序里会导致键盘闪退
隐藏真实 input + 视觉格子是最稳的 H5 方案
核心就一条:所有输入/删除/粘贴都走同一个原生 input,视觉上的六个格子只是纯展示层,用 v-for 渲染 view 即可。真实 input 必须设 type="tel"(不是 number),才能在 iOS/Android 上稳定唤起数字键盘;同时加 inputmode="numeric" 做双重保障。
关键细节:
-
input要用position: absolute; left: -9999px;隐藏,不能用opacity: 0或visibility: hidden——前者在部分 Android 上仍能聚焦但无光标,后者直接不可聚焦 - 每个格子
view绑定@click,里面调this.$nextTick(() => this.$refs.realInput.focus()),确保 DOM 更新后再聚焦 - 监听
@input时,用e.detail.value.replace(/\D/g, '')过滤非数字,再截取前 6 位赋给code响应式变量 - 删除逻辑不用手动管:用户删到空,
code自动变短,视图层v-for渲染自然少一位,光标视觉位置靠code.length决定即可
uni-app 中用 uView 的 u-code-input 怎么快速启用
如果你项目已引入 uView(推荐 v3.2.0+),直接写:
<u-code-input v-model="code" mode="box" :maxlength="6" hairline :space="0" color="#333" border-color="#e5e5e5" dot></u-code-input>
注意三点:
- Vue3 setup 语法糖里,
code必须是ref(''),不能是普通对象属性,否则绑定失效 - 如果搭配自定义键盘(如 uView 的
u-keyboard),必须加disabled-keyboard属性,否则系统键盘和自定义键盘冲突 -
@finish回调里取值,真机测试时建议包一层nextTick或防抖,避免因异步时机导致code还是空字符串
最易被忽略的一点:H5 端没有“失焦即收键盘”的强约束,用户点完验证码后点页面其他区域,input 可能还处于 focus 状态。如果后续有弹窗或滚动操作,软键盘可能意外遮挡内容——得在 @blur 里手动 uni.hideKeyboard(),别只依赖 auto-blur。











