avatar

关于Android设备无法在网页JS中拿到KeyCode的奇怪问题


接到一个奇怪的反馈,称页面上的搜索组件在 Android 设备的浏览器里无法正常工作,原本以为是很简单的问题,没想到掉进了坑里······

起因

某个负责维护的小项目里有一个搜索框,逻辑很简单:按下回车就能执行搜索函数,代码也很简单:onKeyPress 的时候看看 Keyboard Event 的 key 是否为Enter。这个功能在桌面端和 iOS 设备都工作正常,唯独 Android 设备只能从 event 里收到 Unidentified

缘由

一开始以为是使用的废弃的方法 onKeyPress 导致的,遂更换为 onKeyUp方法,在 Android 上测试依然如故。计算机欺我!遂开始谷歌大法进行调查,得到的结论竟然是——这是一个 feature,不是一个 bug,请看:

When using virtual/mobile keyboards, formally known as IME (Input-Method Editor), the W3C standard states that a KeyboardEvent’s e.keyCode should be 229 and e.key should be “Unidentified”.

While some of these keyboards might still use the right values for e.key, e.code, e.keyCode… when pressing certain keys such as arrows or backspace, there’s no guarantee, so your keyboard logic might not always work on mobile devices. https://javascript.info/keyboard-events#mobile-keyboards

简单来说就是,当你使用输入法(IME)的时候,keyboardEvent 只能得到这样的响应:

 {
    key: "Unidentified"
    keyCode: 229
 }

和这个问题有关的 chromium issue https://issues.chromium.org/issues/41443178 自 2019 年就已提交,但是没有收到任何答复。

临时修复

在谷歌上搜索了一圈,似乎并没有什么比较好的办法来拿到真实输入的按键,不过就本文所提到的这种用例,即只想要检测回车按钮的情况,可以用一个小技巧来解决,不知道你还记不记得,HTML 中的什么元素会捕获其子元素的 回车 事件。

答案当然是:

    <form
          onSubmit={(e) => {
            e.preventDefault();
            startSearch();
          }}
        >
          <InputItem
            ...
          />
    </form>

简单,古老,可靠,拯救我于水火之中,希望也能帮到你。