jQuery keypress,keydown,keyup black magic(在Mac上)背后的理论是什么?

我对keypresskeydownkeyup的各种行为感到困惑。 看来我错过了一个重要的文件,一个解释这三个微妙的细节。 有人能帮我弄清楚我需要阅读哪些文件,以便更有效地使用这些事件吗? 如果您需要详细信息,请参阅下文。

@ov:你问我展示一些代码,但是这不是我想要解决的代码中的一个特定问题。 我正试图处理这些事件处理程序的行为,并要求懂得这些事件的人指点我一个很好的文档。

我使用jQuery构build一个input表单并将其插入到我的文档中。 它工作得很好,主要是。 我希望窗体响应键盘,就像我看到的大多数其他input窗体一样: esc键应该忽略与单击取消button相同的窗体,并且由于窗体上有<textarea>cmd +应input与点击确定button相同。 这似乎很简单,使用按键事件。 问题是,Chrome不会调用我的按键处理程序的ESC键或cmd + input 。 它为Ctrl + Enter选项 + input和字母数字,而不是cmd + input火。

所以我会用键盘代替。 我得到了esc的 keyupcmd的 keyup ,还有enter的 keyup ,非常棒。 但是当我按住cmd的时候,我没有得到input键的keyup

第三次的魅力,你可能认为keydown似乎工作,但与keydown ,你会得到重复的钥匙。 我知道,你所要做的就是在你第一次被调用的时候解除绑定,但是三种不同的事件typesperformance得如此不同。 为什么是这样? 那里有一个明显的文件,我显然没有阅读?

按键 :


当浏览器注册键盘input时,keypress事件被发送到一个元素。 这与keyydown事件类似, 除了关键重复的情况 。 如果用户按下并保持一个键,则触发 按键事件 一次 ,但是对于每个插入的字符触发单独的按键事件 。 此外, 修饰键 (如Shift)触发keydown事件,但不是按键事件

Keydown :


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

Keyup :


当用户释放键盘上的键时,键入事件被发送到元素。 它可以附加到任何元素,但事件只发送到具有焦点的元素。 浏览器中的可聚焦元素可能会有所不同,但表单元素总是可以获得焦点,所以这种事件types是合理的候选对象。

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


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

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

请注意,keydown和keyup提供了一个代码,指示哪个按键被按下,而按键显示哪个字符被input。 例如,一个小写的“a”将会被keydown和keyup报告为65,而按键是97。 大写字母“A”在所有事件中报告为65。 由于这个区别, 当捕捉特殊的按键时,例如箭头键,.keydown()或.keyup()是更好的select。

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

本文是解释keyupkeydownkeypress之间差异的一个很好的资源。

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

我亲自处理它在我写的Bootstrap插件的方式是通过创build一个自定义方法来检查支持哪个事件。 巧合的是,一个非常类似的方法在稍后的官方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)); } 

您必须记住,在mac上validationKeyboardEvent时, 修饰键不会被选作event.ctrlKey ,而是一个event.metaKey 。 MDN上提供了更多文档。

没有看到任何代码,我的赌注是这是⌘+Enter没有被拾起的原因。