小小扫码枪bug引发的思考
最近新公司发生了一件bug引发思考的事
产品需求
大致如上图,一个输入框,我们制作了自定义数字键盘,input框可以回显键盘的输入,并且,可以支持扫码枪输入回显
bug描述
在win 系统没有问题,但在安卓系统:
- 每次自定义键盘输入时,还会吊起系统软键盘,且通过系统软键盘输入,input是无法回显的!
- 不支持 扫码枪输入了
最讨厌研究 系统兼容性问题了,但问题出了,就得研究
我们先看一下,自定义数字键盘是怎么实现的?
在了解自定义键盘之前,我先问问大家,键盘输入会触发哪些事件?
对,就是这三个 keydown,keypress, keyup
如何控制Input框只回显数字呢?答案就是在keyDown事件里,通过捕获 event.key来获取用户按下的物理按键的值,非数字的值直接return就能做到了
那么言归正传,自定义键盘怎么实现呢?
其实到这边我们不难想到一个解决方案的思路就是,当按下自定义键盘时,我们模拟一个 keydown事件,并向获得焦点的input 派发这个keydown事件,那么就能模拟键盘输入了
上代码:
const input = document.activeElement
const event = document.createEvent('UIEvents')
event.initUIEvent('keydown', true, true, window, 0)
event.key = key
event.keyCode = -1
input.dispatchEvent(event)
扫码枪又是个啥?
就是这个东东:
去过超市的都看过吧
用扫码枪或者其他设备扫描图形码(条形码或其他码)后将其为文本输入,
input需要识别到扫码枪输入结束,并回显input区,
其实扫码枪输入和用户键盘输入一样都可以触发keydown事件,派发给聚焦的input
那么问题来了?
怎样识别 扫码枪输入结束呢?
答案是onEnter事件
我们再来看看 安卓端出现的bug
1,为啥每次我们在自定义键盘上输入,会同时弹出系统软键盘呢??
问了下安卓侧RD,原来只要input获得焦点,系统键盘就会弹出
但是不聚焦,自定义键盘/扫码枪也没办法回显了呀?
难道真的无解了吗?这时候第n个知识点来了!用readOnly!
readonly,对,就是它,
什么?readonly不是只读吗?有了它,相当于 用户无法输入,因此无法触发系统键盘,这个可以理解,但是,加上它之后,还有焦点吗?
这里有个问题要问大家,你知道readonly和disabled的区别吗?
答案就是在交互上,readonly 仍是可以聚焦的!disabled 就不能了
并且readOnly 是禁止用户输入,所以在允许聚焦的同时,又阻止了软键盘的弹出,这时我不禁感叹: 完美!
2,安卓为啥不支持扫码枪扫码了?
我们通过调试发现,在安卓上,keyDown事件 捕获到的event.key 是 Unidentified, 被我们判定为非数字,直接return了
那解法呢?我们神奇的发现,当我们解了bug1,加上readonly后,bug2也好了!
至于为啥它也好了,具体原因我还不清楚,以下是我的猜测:
前文我们提到,只要input聚焦,软键盘就会弹出,而扫码枪其实也可以看成一个特殊的键盘,可能两个键盘冲突导致 event.key 无法识别,加上readonly禁掉 软键盘后,冲突解除,自然event.key 也可以正常识别了
清楚原因的同学可以留言给我哈!我好想知道!!
反思来了
这件问题的最终解决方案只有一行代码,一个单词: readOnly
简单到令人发指,而且这个问题是一个刚来两天的新同学搞定的
我在想这一连串的故事,太神奇了
为啥这个困扰前辈同学包括我很久的问题,一个萌新一下子就解决了呢?虽然我也是萌新
readOnly可以 解决禁止软键盘弹出,网上的答案是有的,但是我pass了这��方案,
为什么呢?
- input相关基础差,我错误的认为readOnly是只读嘛,肯定会不带焦点啊,虽然禁用了软键盘,但是 扫码枪输入也不能回显了啊
- 当我看到 event.key 是 Unidentified 时,研究重点跑偏了
- 我觉得这可能某种程度上是一种 beginer’s luck, 因为当时新同学的任务是研究如何禁用软键盘,并没有提到其他扫码枪问题,可能这种心无旁骛反而成了事
- 工作中,尤其遇到一些诡异的兼容性问题,真的需要多尝试,不要被自己的想当然绑手绑脚
- 对于兼容性问题,因为要不断尝试,最好找到一种简单方便的调试方法,会大大加快调研进度
最后还是感谢一切的发生,收获了知识,也让我有冲动分享给大家我的一点小思考,感恩感恩!
来源:juejin.cn/post/7388459061758017571