将近一年之前写了个 Vue 相关的验证码输入插件vue-input-code, 一个月之前有个用户提了个 issuse 给我,说无法获取键盘输入,而我一直无法重现.
引言
如果你想试试正常的键盘对应KeyCode
,可以去这个网站KeyCode.
大多数时候我们获取的KeyCode
都是上面那个网站所展示的那样,但是移动端并不遵循这个约定,比如国内的某些厂商...并不清楚这是他们喜欢搞自己的一套,还是说中文输入法故意做成这样.
直到最近一个用户提的一个issuse,我专门去下载了一个讯飞输入法,然后连接电脑调试发现数字键获取的KeyCode
都是一个特殊的数字229
,然后去各种地方搜了一下,发现并没有229
对应的字符.
解决
- 提供一个屏幕内键盘,但是消耗时间太多.
- 使用
ime-mode: disabled;
,Chrome 并不支持,且这个ime-mode已经标记为移除,不会进入 web 标准. - 移除通过判断
KeyCode
来决定是否是数字,直接使用isNaN
.
综上几个方法,第 3 个最简单且可靠,于是采用了这个.
反思
测试的时候应该多使用多个不同类型的输入法测试,尤其移动端中输入法混杂(可能会有各自不同的标准),我一直使用的是 Google 的输入法,所以并没有发现任何问题,直到更换了输入法才发现这个 bug.
如果需要输入字母,则可以通过正则来判断,防止出现类似的问题.
UPDATE
关于keypress
与keydown
的区别可能很多人都不清楚,所以有时候就会遇到一些奇怪的 bug.比如之前在测试组件的时候就发现如果输入过快,会可能导致部分输入框有一个空的值,一直找不到原因.后面才发现使用keyup
(类似 keydown)按键.
Unlike the keypress event, the keydown event is fired for all keys, regardless of whether they produce a character value.
MDN 上的这句描述其实很清楚了,keydown
是监听的所有按键点击,而keypress
只是监听可输入的按键点击,比如alt
这个键使用keypress
是无法监听的.
还有关于keycode
与charcode
的区别,其实也是很简单的:keycode 是一个按键对应的 code,但是你看看你的键盘,是不是有部分按键里面会有两个字符,比如1
有!
这类还有字母,大小写也不知道的,这时候我们监听keypress
这类事件的时候就不知道用户输入的是什么了,因此需要charcode
上场,它代表的是一个char
的 code,因此我们可以通过判断这个知道用户的输入.
总结就是:
- 需要知道用户输入则使用
keypress
并搭配charcode
,比如String.fromCharCode(123)
- 需要监听所有按键则使用
keydown
或者keyup