28

在 Mac 浏览器上,当元键关闭时,javascript 不会接收大多数键的 keyup 事件(其他修饰键似乎是一个例外)。使用这个 jsfiddle 来演示(关注结果区域并尝试类似 cmd + x,x 不会收到 keyup 事件):http: //jsfiddle.net/mUEaV/

我已经在 Chrome、FF、Safari 和 Opera 的稳定版本中复制了这一点。Windows 7 中的控制键似乎不会发生同样的事情。

操作系统是否劫持了 keyup 事件?这似乎特别奇怪,因为使用元键的命令,如保存、查找、剪切、复制等,都在 keydown 而不是 keyup 上激活,并且可以被 javascript 劫持。

4

4 回答 4

6

我今天了解到,使用时根本无法获取onKeyUp事件。meta非常不幸且难以解决。您必须以其他方式模仿它们。

编辑:澄清一下,这仅在 Mac 上并且由于事件的操作系统级别处理而发生。它不能被覆盖。很抱歉成为坏消息的承担者。

于 2019-07-22T20:29:24.953 回答
2

Is the browser window retaining the focus when you press those keys? In windows you can get similar result when pressing windows+R or CTRL+ESC and similar key combinations that make browser to loose focus and that results in missed events.

于 2012-08-05T21:06:02.243 回答
1

尽管 event.metaKey 返回 false,但 event.keyCode 和 event.key 仍然被填充。

document.addEventListener('keyup', function(e) {
    console.log(e.metaKey || e.key);
});
Click here then press the Command, Control, or Option keys.

于 2020-10-06T10:46:33.130 回答
0

您可以通过在最后一个 keydown 事件之后等待一段时间来创建人工 keyup 事件。唯一需要注意的是,人们在他们的操作系统上会有不同的重复率。 https://jsfiddle.net/u7t43coz/10/

const metaKeyCodes = ["MetaLeft", "MetaRight"];
const shiftKeyCodes = ["ShiftLeft", "ShiftRight"];
const ctrlKeyCodes = ["ControlLeft", "ControlRight"];
const altKeyCodes = ["AltLeft", "AltRight"];
const modifierKeyCodes = [
  ...metaKeyCodes,
  ...shiftKeyCodes,
  ...ctrlKeyCodes,
  ...altKeyCodes
];

// record which keys are down
const downKeys = new Set()
const artificialKeyUpTimes = {}

function onKeydown(e) {
    downKeys.add(e.code);

    // do other keydown stuff here
    console.log("meta", e.metaKey, e.code, "down")

    // check if metaKey is down
    if (metaKeyCodes.some(k => downKeys.has(k))) {
      downKeys.forEach(dk => {
        // we want to exclude modifier keys has they dont repeat
        if (!modifierKeyCodes.includes(dk)) {
          // fire artificial keyup on timeout
          if (!artificialKeyUpTimes[dk])
            setTimeout(
              () => fireArtificialKeyUp(dk, e),
              500
            );
          artificialKeyUpTimes[dk] = Date.now();
        }
      });
    }
  }

 function fireArtificialKeyUp(code, e) {
    // if enough time has passed fire keyup
    if (Date.now() - artificialKeyUpTimes[code] > 100) {
      delete artificialKeyUpTimes[code];
      //if key is still down, fire keyup
      if (downKeys.has(code)) {
        const eCode = isNaN(code) ? { code: code } : { keyCode: code };
        document.dispatchEvent(
          new KeyboardEvent("keyup", { ...e, ...eCode })
        );
      }
    } else {
      setTimeout(() => fireArtificialKeyUp(code, e), 100);
    }
  }

  function onKeyup(e) {
    downKeys.delete(e.code);

    // do keyup stuff here
    console.log("meta", e.metaKey, e.code, "up")
  }

  document.addEventListener("keydown", onKeydown)
  document.addEventListener("keyup", onKeyup)
于 2020-05-30T07:15:57.307 回答