不能直接用 type="number" 实现自定义数字键盘,因其在ios、android和微信小程序中软键盘触发行为不一致,且无法控制样式、布局、反馈及输入校验;需用view+@tap构建受控键盘,隐藏真实input,通过js统一处理输入逻辑与格式化。

为什么不能直接用 type="number" 实现自定义数字键盘
因为 iOS 和 Android 对 type="number" 的软键盘触发行为不一致:iOS 弹出带小数点和负号的键盘,Android 可能弹全键盘或拼音键盘;微信小程序则完全忽略该属性,始终调用系统默认键盘。更关键的是,你无法控制按键样式、布局、点击反馈、禁用逻辑,也无法拦截输入内容做校验(比如金额最多两位小数、不能以 0 开头等)。所以「自定义风格」这件事,原生 input 根本不提供入口。
怎么用 view + @tap 搭建轻量可控的键盘结构
核心是把输入框视觉隐藏,用 view 模拟按键,所有输入逻辑由 JS 主动控制。不要绑定 v-model 到 input 上,而是用 data 变量做受控值:
- 把真实
input设为opacity: 0; position: absolute; left: -999rpx;,保留其聚焦能力但不可见 - 键盘按钮用
view布局,每个绑定@tap="onKeyTap('1')"、@tap="onKeyTap('del')" -
onKeyTap内统一处理:数字追加、小数点插入条件判断(!this.value.includes('.') && this.value !== '')、删除逻辑(this.value = this.value.slice(0, -1)) - 显示区域用计算属性
displayValue格式化,比如金额补零、过滤非数字字符,避免模板里写一堆逻辑
iOS 微信小程序里 focus() 和 blur() 容易闪退怎么办
这是真机调试最常卡死的点:iOS 微信对 input 的 focus/blur 频繁切换极其敏感,容易触发渲染异常,表现为键盘闪一下就收、输入框失焦后无法再聚焦。
- 只在键盘首次打开时调一次
uni.focus(),后续按键过程绝不调blur()+focus() - 删除或输入后,如果要保持焦点,改用
this.$nextTick(() => uni.focus()),确保 DOM 更新完成 - 用
confirm-type="done"配合右上角「完成」按钮收起键盘,别监听blur做清理 - 若用
uni.createSelectorQuery()查 input 节点,必须等页面onReady后再执行,否则返回null
怎么让键盘不被系统软键盘遮挡(尤其 iOS)
uni-app 的 input 不会自动滚动到可视区,自定义键盘浮在底部时,极易被系统键盘盖住——这不是样式问题,是 viewport 行为差异导致的。
- Android 可在
manifest.json → app-plus → softinputMode加softKeyboardNav: true - iOS 必须监听
keyboardheight:用uni.onKeyboardHeightChange获取高度,动态设置输入框父容器的padding-bottom或transform: translateY(-${height}rpx) - 务必在页面
onUnload里调uni.offKeyboardHeightChange,否则内存泄漏 - 跨组件查节点(比如键盘组件想定位父页的 input)容易失败,优先用
$refs传入,而不是靠selectComponent穿透查找
onKeyTap 写成字符串拼接(this.value += '1'),结果在金额场景下出现 00.12、.5、123.456 这类非法值。必须把格式化逻辑收口到一个方法里,每次按键都走一遍校验和标准化,而不是依赖用户“别乱按”。











