Obeta

关于JavaScript在移动浏览器中判断输入数字的问题

最近发现的一个怪异的事情,移动端中使用中文输入法时候,获取的KeyCode并不在我们的预期里.

将近一年之前写了个 Vue 相关的验证码输入插件vue-input-code, 一个月之前有个用户提了个 issuse 给我,说无法获取键盘输入,而我一直无法重现.

引言

如果你想试试正常的键盘对应KeyCode,可以去这个网站KeyCode.

大多数时候我们获取的KeyCode都是上面那个网站所展示的那样,但是移动端并不遵循这个约定,比如国内的某些厂商...并不清楚这是他们喜欢搞自己的一套,还是说中文输入法故意做成这样.

直到最近一个用户提的一个issuse,我专门去下载了一个讯飞输入法,然后连接电脑调试发现数字键获取的KeyCode都是一个特殊的数字229,然后去各种地方搜了一下,发现并没有229对应的字符.

解决

  1. 提供一个屏幕内键盘,但是消耗时间太多.
  2. 使用ime-mode: disabled;,Chrome 并不支持,且这个ime-mode已经标记为移除,不会进入 web 标准.
  3. 移除通过判断KeyCode来决定是否是数字,直接使用isNaN.

综上几个方法,第 3 个最简单且可靠,于是采用了这个.

反思

测试的时候应该多使用多个不同类型的输入法测试,尤其移动端中输入法混杂(可能会有各自不同的标准),我一直使用的是 Google 的输入法,所以并没有发现任何问题,直到更换了输入法才发现这个 bug.

如果需要输入字母,则可以通过正则来判断,防止出现类似的问题.

UPDATE

关于keypresskeydown的区别可能很多人都不清楚,所以有时候就会遇到一些奇怪的 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是无法监听的.

还有关于keycodecharcode的区别,其实也是很简单的:keycode 是一个按键对应的 code,但是你看看你的键盘,是不是有部分按键里面会有两个字符,比如1!这类还有字母,大小写也不知道的,这时候我们监听keypress这类事件的时候就不知道用户输入的是什么了,因此需要charcode上场,它代表的是一个char的 code,因此我们可以通过判断这个知道用户的输入.

总结就是:

  • 需要知道用户输入则使用keypress并搭配charcode,比如String.fromCharCode(123)
  • 需要监听所有按键则使用keydown或者keyup

个人随笔记录,内容不保证完全正确,若需要转载,请注明作者和出处.