不推荐使用 KeyboardEvent.keyCode。这在实践中意味着啥?

Posted

技术标签:

【中文标题】不推荐使用 KeyboardEvent.keyCode。这在实践中意味着啥?【英文标题】:KeyboardEvent.keyCode deprecated. What does this mean in practice?不推荐使用 KeyboardEvent.keyCode。这在实践中意味着什么? 【发布时间】:2016-05-25 12:16:27 【问题描述】:

根据 MDN,我们绝对应该使用.keyCode 属性。已弃用:

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

在 W3 学校,这一事实被淡化了,只有一个旁注说 .keyCode 仅用于兼容性,最新版本的 DOM 事件规范建议使用 .key 属性。

问题是浏览器不支持.key,那么我们应该使用什么呢?我有什么遗漏吗?

【问题讨论】:

.key 支持各大浏览器developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/… 【参考方案1】:

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

代替

event.keyCode === 13

这样做

event.key === 'Enter'

【讨论】:

鉴于问题的“实践”部分,这应该是公认的答案。 对于非 ASCII 组合字母,按键事件触发两次。每个是key:'Enter',keyCode:13,key:'Enter',keyCode:229。如何避免没有 keyCode 的第二个事件? @khcpietro 无法用Enter 真正重现它,但有一个isComposing 属性和两个相关事件可能会有所帮助。 event.key所有可能值的列表:developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key/… event.keyCode === 27 变为:event.key === 'Escape'【参考方案2】:

您可以通过三种方式来处理它,因为它写在您共享的链接上。

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);
;

【讨论】:

我确实读过那篇文章,但它似乎有很多额外的代码,除了 MDN 所说的某些内容已被弃用,而实际上它在所有主要浏览器中都可以正常工作。但如果这是正确的方法,那么谢谢! 哇,这个。 caniuse.com/#search=keyCode(所有浏览器都有效地支持此 KeyboardEvent 属性(从 IE6+、Firefox 2+、Chrome 1+ 等“谈论 .keyCode”) 这就是这一切令人讨厌的地方。所有主流浏览器都支持 keyCode,但请尝试检查 .key 属性,这是推荐的,几乎没有人使用它! 是的,直到 2016 年 5 月下旬,chrome 终于实现了 KeyboardEvent.key 属性。 Safari 和所有移动浏览器尚未加入“占所有用户的 16.5%”的队伍。此外,遗憾的是,Microsoft Edge 和 Gecko 对很多事件进行了不同的编码,例如:向上箭头的键事件被编码为“Up”而不是“ArrowUp”。 但是event.key 是一个字符串,而event.keyCode 是一个数字,对吧?鉴于它们甚至没有相同的类型,它们是否可以具有相同的语义?还是你的意思是event.code【参考方案3】:

TLDR:我建议您应该使用新的event.keyevent.code 属性而不是旧属性。 IE 和 Edge 支持这些属性,但还不支持新的键名。对于他们来说,有一个小的 polyfill 可以让他们输出标准的键/代码名称:

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


我来这个问题是为了寻找与 OP 相同的 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被替换的原因之后,我们来看看你今天需要做什么:

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

【讨论】:

According to the MDN,Internet Explorer 和 Edge 都不支持 KeyboardEvent.code。此外,keycode 的值取决于浏览器。这两个问题使keycode 在现实生活中的应用程序中不实用。 @JohnSlegers 请参阅developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key 如果我想测试方向键、向上/向下翻页、主页和结尾,我应该使用key 还是code?它通常是物理键,但也可以取决于 Num Lock 和布局...最佳做法是什么? string 也使它更具可读性,因此建议将它用于所有新代码。为了维护遗产,这将取决于您对它作为number 的依赖程度。请注意,当您按下可打印键时,event.key“a”和“A”是不同的,而event.code 将是“keyA”。对于不可打印,您可以让event.code 成为“ShiftLeft”或“ShiftRight”,而event.key 将成为“Shift”。【参考方案4】:

此外,keyCode、which、charCode 和 keyIdentifier 均已弃用:charCodekeyIdentifier 是非标准功能。keyIdentifier 已删除从 Chrome 54 和 Opera 41.0 开始keyCode 在 FF 上使用普通字符的按键事件时返回 0。

The key property:

 readonly attribute DOMString key

持有与按下的键对应的键属性值

截至撰写本文时,所有主流浏览器都支持 key 属性:Firefox 52、Chrome 55、Safari 10.1、Opera 46。除了 Internet Explorer 11,它具有: 非标准键标识符和 AltGraph 的错误行为。 More info 如果这很重要和/或向后兼容性很重要,那么您可以使用如下代码中的特征检测:

注意keyvalue 与keyCodewhich 属性的不同之处在于:它包含键的名称而不是其代码。如果您的程序需要字符代码,那么您可以使用charCodeAt()。 对于单个可打印字符,您可以使用 charCodeAt(),如果您正在处理其值包含多个字符(如 ArrowUp)的键 机会是:您正在测试特殊键并采取相应措施。所以尝试实现一个键值表及其对应的 代码charCodeArr["ArrowUp"]=38,charCodeArr["Enter"]=13,charCodeArr[Escape]=27...等等,请看Key Values和他们的corresponding codes

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 属性 docs 以及此 answer 中的更多详细信息。

【讨论】:

您的解决方案在我的浏览器(Windows 10、Chrome 60、比利时键盘)中不起作用。首先,charCodeArr 函数不存在。此外,charCodeAt 不适用于 e.key 的所有值。例如,对于Enter / Return 键,e.key 属性的值为"Enter",并且对该字符串执行charCodeArr 将返回值69(这是字符@ 987654357@). @JohnSlegers,是的,这是一个错字,我的意思是用户构建的数组。请参阅我的更新答案以获取更多详细信息。【参考方案5】:

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);

【讨论】:

不幸的是,key 是浏览器特定的字符串值,例如 "Enter""ArrowUp",并且没有标准化的方法可以将其转换为相应的代码。因此,您将需要更多样板代码来在密钥和代码之间进行转换。【参考方案6】:

e.charCode 已被弃用:

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

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

【讨论】:

【参考方案7】:

这里建议使用 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);
);

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

【讨论】:

【参考方案8】:
(e)=>
  e.key === 'Escape';

相同
(e)=>
  e.keyCode === 27;

最好用第二个。

【讨论】:

它没有回答这个问题。为什么使用keyCode 会更好?您是否检查过任何赞成的答案?【参考方案9】:

你可以使用

parseInt(event.key, radix: 10)

【讨论】:

请不要只发布代码作为答案,还要解释您的代码的作用以及它如何解决问题的问题。带有解释的答案通常更有帮助、质量更好,并且更有可能吸引投票

以上是关于不推荐使用 KeyboardEvent.keyCode。这在实践中意味着啥?的主要内容,如果未能解决你的问题,请参考以下文章

为啥不推荐使用 (javax.servlet.)SingleThreadModel?

为什么不推荐使用 BeanUtils ?

为什么不推荐使用 BeanUtils ?

如何设置相机视图旋转(不使用不推荐使用的代码)

为啥 PoolingClientConnectionManager 中不推荐使用所有方法?

不推荐使用 invalidateOptionsMenu()