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

KeyboardEvent.keyCode deprecated. What does this mean in practice?

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

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

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

问题是浏览器不支持.key,那我们应该用什么?有什么我想念的吗?

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

你有三种方法来处理它,因为它写在你分享的 link 上。

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

此外,所有 keyCode, which, charCode and keyIdentifier 都已弃用:
charCodekeyIdentifier 是非标准特征。
keyIdentifier 从 Chrome 54 和 Opera 41.0
开始删除 keyCode returns 0,在 FF 上具有正常字符的按键事件。

The key property :

 readonly attribute DOMString key

Holds a key attribute value corresponding to the key pressed

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

请注意 key 值与 keyCodewhich 属性的不同之处在于:它包含键的名称而不是其代码。如果您的程序需要字符代码,那么您可以使用 charCodeAt()。 对于单个 printable 字符,您可以使用 charCodeAt(),如果您正在处理其值包含多个字符的键,例如 ArrowUp 机会是:您正在测试特殊键并采取相应的措施。所以尝试实现一个 table 的键值及其对应的 代码charCodeArr["ArrowUp"]=38charCodeArr["Enter"]=13charCodeArr[Escape]=27...等等,请看Key Values and their 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 and some more details in this answer.

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

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


我来到这个问题是为了寻找与 OP 相同的 MDN 警告的原因。经过更多搜索,keyCode 的问题变得更加清楚:

使用 keyCode 的问题是非英语键盘会产生不同的输出,甚至具有不同布局的键盘也会产生不一致的结果。另外,还有

的情况

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

In practice, keyCode and charCode are inconsistent across platforms and even the same implementation on different operating systems or using different localizations.

它深入描述了 keyCode 出了什么问题: https://www.w3.org/TR/uievents/#legacy-key-attributes

These features were never formally specified and the current browser implementations vary in significant ways. The large amount of legacy content, including script libraries, that relies upon detecting the user agent and acting accordingly means that any attempt to formalize these legacy attributes and events would risk breaking as much content as it would fix or enable. Additionally, these attributes are not suitable for international usage, nor do they address accessibility concerns.

那么,在确定了遗留 keyCode 被替换的原因之后,让我们看看您今天需要做的事情:

  1. 所有现代浏览器都支持新属性(keycode)。
  2. IE 和 Edge 支持旧版本的规范,其中一些键的名称不同。您可以为此使用垫片: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/

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

而不是

event.keyCode === 13

喜欢

event.key === 'Enter'

您可以使用

parseInt(event.key, radix: 10)
(e)=>{
  e.key === 'Escape';
}

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

用第二个比较好

这里建议使用 key 值而不是 keyCode 如果失败则使用 keyCode.虽然这还不够,因为此属性中的值不兼容。事情是新的 key 包含控制键的字符串,例如:ArrowUp,但是 keyCode 将只包含带有 trivial

的代码
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);
});

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

e.charCode 已弃用:

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

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