键码查看器

按下按键即可读取 KeyboardEvent 的全部属性:key、code、keyCode、which、location 以及 ctrl、shift、alt、meta 标志,并可复制完整 JSON。

按下一个键,看看浏览器究竟报告了什么。 点击下方捕获区域,然后按下任意按键或组合键。KeyboardEvent 的每个属性都会并排显示,让你在编写快捷键处理逻辑时能选对属性,而不是靠猜。

event.key
event.code
event.keyCode
event.which
event.location
按下的修饰键

key、code 与 keyCode 并不是一回事

三个属性,三个不同的问题

KeyboardEvent 提供了多种标识按键的方式,它们回答的问题其实各不相同。event.key 是在应用键盘布局和修饰键之后,按键所产生的字符或具名值。按下物理 A 键得到 a,同时按住 Shift 得到 A,而在 Dvorak 或 AZERTY 布局上则可能是完全不同的字母。具名按键会以描述性字符串出现,例如 EnterEscapeArrowLeftF5

event.code 标识的则是物理按键位置,使用一套与布局无关、基于假想美式键盘的名称。位于 A 键位置的按键始终是 KeyA,无论用户布局实际输出什么。顶部数字行是 Digit1Digit0,数字小键盘则报告 Numpad1 之类的名称,因此你能区分两排数字。

event.keyCode 及其孪生的 event.which 是遗留的数字标识符。二者在规范上均已废弃,却依然在所有浏览器中实现,并且对标点符号的取值在各浏览器间并不一致。维护老代码时它们仍值得关注,但新的快捷键处理应当使用 keycode

在 key 和 code 之间做选择

经验法则很简单:位置重要时用 code,含义重要时用 key。把移动绑定到 WASD 的游戏应该用 code,因为玩家左手下方的那一簇物理按键在 AZERTY 键盘上应保持原位,尽管它实际输出的是 ZQSD。把「保存」绑定到 Ctrl+S 的文本编辑器则应该用 key,因为用户想到的是字母 S,而不是 A 旁边的那个键。

修饰键是独立的布尔值:ctrlKeyshiftKeyaltKeymetaKey。请显式检测它们,而不要从 key 推断;同时要记住主快捷键修饰符在 macOS 上是 Command,在其他平台上是 Control。常见写法是接受 event.metaKey || event.ctrlKey,让同一段处理逻辑覆盖两个平台。

event.location 用于区分重复按键。标准按键为 0,成对按键中的左侧(如左 Shift)为 1,右侧为 2,数字小键盘上的按键为 3。

实践中的坑

并非所有按键都会产生你期望的事件。浏览器会为自己保留一些组合——Ctrl+W、Ctrl+T 和 Command+Q 通常在页面看到之前就已关闭标签页或退出应用,preventDefault 也无法夺回它们。任何快捷键都应在真实浏览器窗口中测试,而不要假定它一定能到达你的处理函数。

按住某个键会在首次事件之后产生一连串重复事件,其 event.repeat 为 true。若快捷键只应触发一次,就忽略重复事件;若行为是连续性的(例如滚动或移动光标),则应当响应它们。

最后,keydownkeyup 描述的是按键,而描述字符的 keypress 已从标准中移除。处理文本输入时,更推荐监听 input 事件或读取 beforeinput,它们对输入法组字、自动完成和移动端键盘的处理都远比任何按键级事件可靠。

开源说明:使用原生 JavaScript 实现,不依赖第三方库。

常见问题

快捷键应该用 key 还是 code?
物理位置重要时用 `code`,例如游戏中的 WASD 移动;含义重要时用 `key`,例如保存用的 Ctrl+S,这样快捷键会跟随用户自己的键盘布局。
keyCode 既然废弃了为什么还能用?
它早于支持布局感知的事件出现,且对标点符号在各浏览器返回的数字并不一致。所有引擎出于兼容性仍在实现它,但规范建议新代码使用 `key` 和 `code`。
按 Ctrl+W 或 Command+Q 没有任何反应。
这些组合被浏览器或操作系统占用,在页面收到之前就已被处理。普通网页没有可靠的方式拦截它们。
如何写一个同时适配 macOS 和 Windows 的快捷键?
用 `event.metaKey || event.ctrlKey` 接受任一主修饰键。它在 macOS 上对应 Command,在 Windows 和 Linux 上对应 Control,无需按 User-Agent 分支处理。
location 为 3 是什么意思?
表示该键位于数字小键盘上。1 和 2 分别表示 Shift、Control 这类成对按键的左侧和右侧,0 表示没有重复的普通按键。
可以用它来实现文本输入处理吗?
更好的做法是监听 `input` 事件。按键事件会遗漏输入法组字、自动完成以及许多移动端虚拟键盘的输入,而这些 `input` 都能正确上报。