49

我对keypresskeydownkeyup的各种行为感到困惑。似乎我错过了一份重要的文档,该文档解释了这三人组的微妙之处和细微差别。有人可以帮我弄清楚我需要阅读哪个文件才能更有效地使用这些事件吗?如果您需要详细信息,请参见下文。

@ov:你让我展示一些代码,但这并不是我试图解决的代码中的一个具体问题。我试图掌握这些事件处理程序的行为,并要求了解它们的人向我指出一份好的文档。

我使用 jQuery 构建输入表单并将其插入到我的文档中。它工作得很好,主要是。我希望表单像我看到的大多数其他输入表单一样响应键盘:esc键应该像单击取消按钮一样关闭表单,并且由于表单上有一个<textarea>cmd+enter应该与单击相同确定按钮。使用keypress事件似乎很简单。问题是 Chrome 没有调用我的keypress处理程序来获取esckey 或cmd+ enter。它会触发ctrl+enteroption+enter以及字母数字,但不会触发cmd+ enter

所以我会改用keyup。我得到keyup for esckeyup for cmdkeyup for enter,太棒了。但是当我按住时我没有得到的键位。entercmd

第三次的魅力,你可能认为keydown似乎工作,但使用keydown,你会得到重复键。我知道,您所要做的就是在第一次调用时取消绑定处理程序,但是这三种不同的事件类型的行为如此不同似乎很奇怪。为什么是这样?那里有我显然没有读过的明显文件吗?

4

3 回答 3

90

按键


当浏览器注册键盘输入时,keypress 事件被发送到元素。这类似于 keydown 事件,除了在 key repeats 的情况下。如果用户按住某个键,则会触发一次keydown 事件,但会为每个插入的字符触发单独的 keypress 事件。此外,修饰键(如 Shift)会触发 keydown 事件,但不会触发 keypress 事件

按键


当用户第一次按下键盘上的键时,keydown 事件被发送到元素。它可以附加到任何元素,但事件只发送到具有焦点的元素。可聚焦元素 在浏览器之间可能会有所不同,但表单元素总是可以获得焦点,因此是此事件类型的合理候选者。

键位


当用户在键盘上释放一个键时,keyup 事件被发送到一个元素。它可以附加到任何元素,但事件只发送到具有焦点的元素。可聚焦元素在浏览器之间可能会有所不同,但表单元素总是可以获得焦点,因此是此事件类型的合理候选者。

此外,这是一个方便的信息,通常被掩盖:


如果需要捕获任何地方的按键(例如,在页面上实现全局快捷键),则将此行为附加到文档对象很有用。由于事件冒泡,除非明确停止,否则所有按键都会沿 DOM 向上到达文档对象。

要确定输入了哪个字符,请检查传递给处理函数的事件对象。虽然浏览器使用不同的属性来存储这些信息,但 jQuery 对.which 属性进行了规范化,因此您可以可靠地使用它来检索字符代码

请注意,keydown 和 keyup 提供了指示按下哪个键的代码,而 keypress 指示输入了哪个字符。例如,小写字母“a”将被 keydown 和 keyup 报告为 65,但被 keypress 报告为 97。所有事件都将大写“A”报告为 65。由于这种区别,当捕获特殊按键(如箭头键)时,.keydown() 或 .keyup() 是更好的选择。

cmd有关MAC 上的键的更多信息:命令键的 jQuery 键代码

于 2012-10-10T20:09:22.750 回答
5

本文是一个很好的资源,用于解释和之间keyup的区别。 keydownkeypress

简短的回答是,除了考虑不同的浏览器之外,没有简单的方法来处理它们。

我个人在我编写的 Bootstrap 插件中处理它的方式是创建一个自定义方法来检查支持哪个事件。巧合的是,不久之后官方 Bootstrap 版本中出现了一个非常相似的方法:P

//------------------------------------------------------------------
//
//  Check if an event is supported by the browser eg. 'keypress'
//  * This was included to handle the "exhaustive deprecation" of jQuery.browser in jQuery 1.8
//
eventSupported: function(eventName) {         
    var isSupported = (eventName in this.$element);

    if (!isSupported) {
      this.$element.setAttribute(eventName, 'return;');
      isSupported = typeof this.$element[eventName] === 'function';
    }

    return isSupported;
}

后来我在我的代码中使用它来附加事件处理程序:

if (this.eventSupported('keydown')) {
  this.$element.on('keydown', $.proxy(this.keypress, this));
}
于 2012-10-10T20:09:10.933 回答
1
于 2012-10-11T01:43:43.700 回答