KeyboardEvent.keyCode被弃用了。在实践中,这意味着什么?

282
根据MDN的说法,我们绝对不应该使用.keyCode属性。它已经被弃用:

https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/keyCode

在W3School上,这个事实被淡化了,只有一个侧面说明说.keyCode仅提供兼容性,并且DOM事件规范的最新版本建议使用.key属性。问题是,浏览器不支持.key,那么我们应该使用什么?我有什么遗漏的吗?

8
.key 在所有主流浏览器中都有支持。详情请参考 https://developer.mozilla.org/zh-CN/docs/Web/API/KeyboardEvent/key#Browser_compatibility - sbolel
这个问题似乎不再特别有用,因为所有现代浏览器都支持 event.key - Herohtar
9个回答

243

例如,如果您想检测是否单击了“Enter”键:

可以使用以下代码:

event.keyCode === 13

像这样去做

event.key === 'Enter'

8
鉴于问题中的“实践”部分,这应该是被接受的答案。 - Eduardo Pignatelli
3
对于非ASCII组合字母,按键事件会触发两次。它们分别是{ key: 'Enter',keyCode: 13 },{ key: 'Enter',keyCode: 229 }。如何避免没有keyCode的第二个事件? - khcpietro
4
所有可能的event.key值列表:https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key/Key_Values - Christopher K.
5
event.keyCode === 27 翻译为 event.key === 'Escape' - Gil Epshtain
17
请记住,将代码中的 event.keyCode === 13 修改为 event.key === 'Enter' 将取消对数字键盘按键的支持。如果要同时支持两种方式,请使用以下代码:event.key === 'Enter' || event.key === 'NumpadEnter'或者更好的选择是:['Enter', 'NumpadEnter'].includes(event.key) - Austin Arnett
显示剩余3条评论

75

你可以按照你分享的链接上所写的三种方法来处理它。

if (event.key !== undefined) {

} else if (event.keyIdentifier !== undefined) {

} else if (event.keyCode !== undefined) {

}

如果你想要跨浏览器支持,那么你应该考虑这些内容,这是正确的方式。

如果你实现类似这样的东西,它可能会更容易。

var dispatchForCode = function(event, callback) {
  var code;

  if (event.key !== undefined) {
    code = event.key;
  } else if (event.keyIdentifier !== undefined) {
    code = event.keyIdentifier;
  } else if (event.keyCode !== undefined) {
    code = event.keyCode;
  }

  callback(code);
};

24
我看过那个,但似乎有很多额外的代码,只是因为MDN说某些东西已经过时了,实际上在所有主流浏览器中都可以正常工作。但是如果那是正确的方式,那就谢谢了! - Jason210
4
哇,看这个。http://caniuse.com/#search=keyCode(这个KeyboardEvent属性在几乎所有浏览器中都受支持(自IE6+、Firefox 2+、Chrome 1+等以来“谈论.keyCode”)。 - Miguel Lattuada
6
所有这一切的令人烦恼之处就在于此。所有主要浏览器都支持keyCode,但尝试检查推荐使用的.key属性时,很少有人使用它! - Jason210
4
没错,现在已经是2016年5月底了,Chrome浏览器终于实现了KeyboardEvent.key属性。Safari和所有移动浏览器尚未加入“所有用户的16.5%”派对。不幸的是,Microsoft Edge和Gecko对许多事件进行了不同的编码,例如:向上箭头键的关键事件被编码为“Up”,而不是“ArrowUp”。 - Joshua Dawson
6
event.key 是一个字符串,而 event.keyCode 是一个数字,对吧?考虑到它们甚至没有相同的类型,它们怎么可能有相同的语义呢?或者你是指 event.code 吗? - bluenote10
显示剩余5条评论

49

简述:建议您使用新的event.keyevent.code属性而非之前的遗留属性。IE和Edge支持这些属性,但尚不支持新的键名。对于它们,有一个小型填充程序可以使它们输出标准的键名/代码:

https://github.com/shvaikalesh/shim-keyboard-event-key


我查找了同样MDN警告的原因,发现 keyCode的问题更为明显:

使用keyCode的问题在于,非英语键盘可能会产生不同的输出,即使是具有不同布局的键盘也会产生不一致的结果。此外,还有以下情况:

如果您阅读W3C规范:https://www.w3.org/TR/uievents/#interface-keyboardevent

实际上,keyCode和charCode在不同平台甚至同一操作系统的不同实现或使用不同本地化时存在不一致性。

它详细描述了keyCode的问题:https://www.w3.org/TR/uievents/#legacy-key-attributes

这些功能从未被正式指定,当前的浏览器实现在很多方面存在不同。大量遗留内容(包括脚本库)依赖于检测用户代理并相应地采取行动,意味着任何试图形式化这些遗留属性和事件的尝试都会冒险破坏与修复/启用同样数量的内容。此外,这些属性不适合国际使用,也不能解决辅助功能问题。

因此,在确定了为什么要替换旧的keyCode之后,让我们看一下今天您需要做什么:

  1. 所有现代浏览器都支持新属性(keycode)。
  2. IE和Edge支持旧规范的较早版本,其中某些键具有不同的名称。您可以使用这个shim:https://github.com/shvaikalesh/shim-keyboard-event-key (或自己编写 - 它相当小)
  3. Edge在最新版本中修复了此错误(可能会在2018年4月发布) - https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/8860571/
  4. 请参考您可以使用的事件键列表:https://www.w3.org/TR/uievents-key/

根据MDN的说法,Internet Explorer和Edge都不支持KeyboardEvent.code。此外,keycode的值也取决于浏览器。这两个问题都使得在实际应用中使用keycode变得不切实际。 - John Slegers
@JohnSlegers 请查看 https://developer.mozilla.org/zh-CN/docs/Web/API/KeyboardEvent/key - kumarharsh
1
如果我想测试箭头键、上/下翻页键、Home 和 End 键,我应该使用 key 还是 code?通常这是一个物理键,但也可能取决于 Num Lock 和布局...最佳实践是什么? - Jake
3
它作为一个“字符串”也使得它更易读,因此建议在所有新代码中使用它。对于维护遗留代码,这将取决于您对它作为“数字”的依赖程度。只需注意,当您按下可打印键时,“event.key”中的“a”和“A”是不同的,而“event.code”对于两者都将是“keyA”。对于不可打印的键,您可以将“event.code”设置为“ShiftLeft”或“ShiftRight”,而“event.key”对于两者都将是“Shift”。 - Guilherme Taffarel Bergamin

33

除了所有的keyCodewhichcharCodekeyIdentifier都已被废弃:
charCodekeyIdentifier 是非标准特性。
keyIdentifier 自 Chrome 54 和 Opera 41.0 开始被移除。
在 Firefox 上,keyCode 在按下普通字符时返回 0。

The key property

 readonly attribute DOMString key

保存键按下时对应的关键属性值

截至本文撰写时,key属性已被所有主要浏览器支持: Firefox 52、Chrome 55、Safari 10.1、Opera 46。但是Internet Explorer 11存在以下问题:非标准的键标识符和AltGraph不正确的行为。更多信息
如果这很重要或者需要向后兼容,则可以使用功能检测,如下面的代码:

请注意:key值与keyCodewhich属性不同,因为它包含键的名称而不是其代码。如果您的程序需要字符代码,则可以使用charCodeAt()。对于单个可打印字符,您可以使用charCodeAt();如果您处理的是包含多个字符的键值,例如ArrowUp,则可能正在测试特殊键并相应地采取措施。因此,请尝试实现一个表格,其中包含键的值及其相应的代码charCodeArr["ArrowUp"]=38charCodeArr["Enter"]=13charCodeArr[Escape]=27等等,请查看键值及其相应的代码

if(e.key!=undefined){
        var characterCode = charCodeArr[e.key] || e.key.charCodeAt(0);
    }else{
        /* As @Leonid suggeted   */
        var characterCode = e.which || e.charCode || e.keyCode || 0;
    }
        /* ... code making use of characterCode variable  */  

也许你想考虑向前兼容,即在可用的情况下使用旧属性,只有在这些属性被弃用后才切换到新属性:

if(e.which || e.charCode || e.keyCode ){
        var characterCode = e.which || e.charCode || e.keyCode;
    }else if (e.key!=undefined){
        var characterCode = charCodeArr[e.key] || e.key.charCodeAt(0);
    }else{
        var characterCode = 0;
    }

另请参阅:文档中的KeyboardEvent.code属性,以及此答案中的更多详细信息。


1
你的解决方案在我的浏览器(Windows 10,Chrome 60,比利时键盘)中无法工作。首先,charCodeArr函数不存在。此外,charCodeAt对于所有值的e.key都不起作用。例如,对于“Enter”/“Return”键,e.key属性的值为“Enter”,并且执行该字符串的charCodeArr返回值为69(这是字符E的ASCII代码)。 - John Slegers
@JohnSlegers,是的,那是一个打字错误,我指的是用户构建的数组。请查看我的更新答案以获取更多详细信息。 - user10089632

18

MDN已经提供了解决方案:

https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/keyCode

window.addEventListener("keydown", function (event) {
  if (event.defaultPrevented) {
    return; // Should do nothing if the default action has been cancelled
  }

  var handled = false;
  if (event.key !== undefined) {
    // Handle the event with KeyboardEvent.key and set handled true.
  } else if (event.keyIdentifier !== undefined) {
    // Handle the event with KeyboardEvent.keyIdentifier and set handled true.
  } else if (event.keyCode !== undefined) {
    // Handle the event with KeyboardEvent.keyCode and set handled true.
  }

  if (handled) {
    // Suppress "double action" if event handled
    event.preventDefault();
  }
}, true);

5
很遗憾,“key”是浏览器特定的字符串值,例如“Enter”或“ArrowUp”,并且没有标准化的方法将其转换为相应的代码。因此,您需要编写更多的样板代码来在键和代码之间进行转换。 - John Slegers

7

e.charCode 已被弃用:

<input
  onChange={(e) => setToken(e.target.value)}
  type="text"
  value={token}
  onKeyPress={(e) => {
    if (e.charCode === 13) {
      verifyLoginF()
    }
  }}
/>

输入图像描述这里

现在应该使用:e.key === 'Enter'

输入图像描述这里


2

建议使用键值(key)而不是按键码(keyCode),如果失败了再使用按键码(keyCode)。然而这还不够,因为这些属性中的值不兼容。问题在于新的键值(key)包含控制键的字符串,例如:ArrowUp,但按键码(keyCode)只包含简单的代码。

String.fromCharCode(event.keyCode)

输入非可打印字符会导致问题,以下是可打印字符的解决方案:

element.keydown((event) => {
    var symbolPressed;
    //cross browser
    if (event.key !== undefined) {
        symbolPressed = event.key; //Here control characters represented as String like: ArrowUp
        if (symbolPressed.length > 1) return; //filter out control characters
    } else if (event.keyCode !== undefined) {
        symbolPressed = String.fromCharCode(event.keyCode); //Here control chars represented as one char string
    }
    //Update this regex if you need other characters
    if (!symbolPressed.match(/[A-z0-9\s]/)) return;
    console.log(symbolPressed);
});

如果您需要非可打印的控制字符,您需要相应地更新条件和正则表达式。


-1

使用 onkeypress 和 onkeydown 事件来获取 event.which,它可以切换 [字符代码] 或 [键代码]

 function myKey(event){
 
  var keycode = event.keyCode;  //key code variant 1, not recomendate
  var keywhic = event.which;    //key code variant 2, nice worked 
  var unicode = event.key;      //string name code, nice worked  
  var chacode = event.charCode; //works onkeypress="myKey(event)"
  var metakey = event.metaKey;  //true false, winKey or macComand
  
  document.getElementById("demo").innerHTML = keycode+" "+keywhic+" "+unicode+" "+chacode+" "+metakey;
}
<!DOCTYPE html>
<html>
<body onkeydown="myKey(event)"> <!--onkeypress="myKey(event)"-->

<h1 id="demo">Keyboard Buttons click me and test the keyboard</h1>
<script>
 //function myKey(event){
 //paste code
 //}
</script>
</body>
</html>


-5

您可以使用

parseInt(event.key, radix: 10)

5
请勿仅以代码形式回答问题,同时提供代码解决问题的方法和原理说明。带有解释的答案通常更有价值、更优质,并且更可能吸引赞同。 - Ran Marciano

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接