真正可控的数字键盘需手写view+事件模拟,因type="number"多端兼容差;v-model失效因依赖原生事件,应改用data变量+watch+emit同步;各端键盘适配策略差异大,需分别处理聚焦、遮挡、定位等问题。

不能靠 input 的 type="number" 实现真正可控的数字键盘——iOS 弹带小数点和负号的键盘,Android 可能直接出拼音键盘,微信小程序压根不认这个 type。多端一致的数字键盘,必须手写 view + 事件模拟,且各端交互逻辑差异极大。
为什么 v-model 在自定义键盘里会失效
因为 v-model 依赖原生 input 元素的 input 和 change 事件,而你点击的是 view 按钮,不会触发这些事件。强行绑定会导致父组件收不到更新、清空后输入变成 "01"、小数点重复插入等错乱。
- 用
data中独立变量(如payValue)存当前值,所有按键操作只改它 - 用
watch监听该变量,通过this.$emit('update:value', newValue)向上同步 - 显示层用计算属性
displayValue格式化:过滤非法字符、限制小数位、补零(如金额显示"12.00") - 按钮的
value统一传字符串('1'、'.'、'delete'),避免类型隐式转换出错
iOS 微信小程序里键盘闪退、失焦怎么办
iOS 微信下频繁调 focus()/blur() 极易触发渲染异常,表现为键盘闪一下就收、再点输不了。这不是 bug,是 WebView 渲染机制限制。
- 只在键盘首次打开时调一次
uni.focus(),后续按键不再触发聚焦 - 删除键逻辑要判空:
if (this.payValue) this.payValue = this.payValue.slice(0, -1),否则"".slice(0, -1)返回空字符串但可能引发异常 - 用
confirm-type="done"配合右上角「完成」收起键盘,别监听blur做清理 - 若需动态获取 input 节点,必须等页面
onReady后再用uni.createSelectorQuery(),否则返回null - 修改值后要等 DOM 更新再聚焦:
this.$nextTick(() => uni.focus())
软键盘遮挡输入框,各端怎么分别处理
这不是 CSS 能解决的问题。H5 自动滚动,App 端和小程序行为完全不同,尤其 iOS 不会自动推高内容区。
- Android App:在
manifest.json → app-plus → softinputMode设为adjustResize或adjustPan - iOS App / 小程序:必须监听
keyboardheight:uni.onKeyboardHeightChange(({height}) => { this.keyboardHeight = height }),然后用transform: translateY(-${height}px)或padding-bottom抬升输入区域 - H5:可用
scrollIntoView({ behavior: 'smooth', block: 'nearest' }),但真机调试时部分 Android 浏览器不支持 - 务必在
onUnload里调uni.offKeyboardHeightChange,否则内存泄漏
nvue 页面和 vue 页面键盘实现差异在哪
支付类场景强烈建议用 nvue 页面写键盘——性能高、动画顺、无白屏。但 nvue 下 DOM 操作完全不可用,必须换思路。
- nvue:用
position: fixed+bottom: 0定位键盘,按钮用@click,禁用原生 input 的聚焦:focusable="false"或user-select: none - vue 页面:用
transform: translateY()控制弹出,但需手动处理 iOS 键盘顶起时的 viewport 缩放问题 - nvue 不支持
document.querySelector,查节点必须用this.$refs.xxx;vue 下才可用uni.createSelectorQuery() - App 端根本不用管
uni.showKeyboard——这 API 在 App 端静默失败,连错误都不报
最易被忽略的是:键盘按钮的 keyCode 映射不能硬写数字(比如 49 对应 '1'),安卓和 iOS 的 keyEvent.keyCode 不一致,统一用字符映射表更稳;还有,密码类键盘必须禁用复制粘贴、禁用长按菜单、掩码显示不能靠 type="password",得用 * 拼接 text 节点。











