jQuery 按键、按键、按键黑魔法(在 Mac 上)背后的理论是什么?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/12827408/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
What's the theory behind jQuery keypress, keydown, keyup black magic (on Macs)?
提问by SaganRitual
I am confused about the various behaviors of keypress, keydown, and keyup. It seems that I have missed an important piece of documentation, one that explains the subtleties and nuances of this trio. Could someone help me to figure out which document I need to read in order to more effectively use these events? In case you want details, see below.
我对keypress、keydown和keyup的各种行为感到困惑。似乎我错过了一份重要的文档,它解释了这三重奏的微妙之处和细微差别。有人可以帮我弄清楚我需要阅读哪个文档才能更有效地使用这些事件吗?如果您需要详细信息,请参见下文。
@o.v.: you asked me to show some code, but it's not really a specific problem in the code that I'm trying to solve. I'm trying to get a handle on the behaviors of these event handlers and asking someone who understands them to point me to a good piece of documentation.
@ov:你让我展示一些代码,但这并不是我试图解决的代码中的一个具体问题。我正在尝试了解这些事件处理程序的行为,并请了解它们的人向我指出一份很好的文档。
I use jQuery to build an input form and insert it into my document. It works just fine, mostly. I want the form to respond to the keyboard like most other input forms I see out there: the esckey should dismiss the form the same as clicking the cancel button, and because the form has a <textarea>
on it, cmd+ entershould be the same as clicking the OKbutton. It seems simple enough to use the keypressevent. The problem is that Chrome doesn't call my keypresshandler for the esckey or cmd+ enter. It fires for ctrl+ enterand option+ enterand for alphanumerics, but not cmd+ enter.
我使用 jQuery 构建一个输入表单并将其插入到我的文档中。它工作得很好,主要是。我希望表单像我在那里看到的大多数其他输入表单一样响应键盘:esc键应该像单击取消按钮一样关闭表单,并且因为表单上有一个<textarea>
,cmd+enter应该与单击相同确定按钮。使用keypress事件似乎很简单。问题是 Chrome 不会为key 或+调用我的按键处理程序。它激发了+和+和字母数字,但不+ 。esccmdenterctrlenteroptionentercmdenter
So I'll use keyupinstead. I get keyupfor esc, and keyupfor cmd, and keyupfor enter, great. But I don't get keyupfor the enterkey while I'm holding down cmd.
所以我会用keyup代替。我得到keyupfor esc,keyupfor cmd,keyupfor enter,太好了。但我没有得到KEYUP了enter,而我按住键cmd。
Third time's the charm, you might think keydownseems to work, but with keydown, you get repeat keys. I know, all you have to do is unbind the handler the first time you're called, but it just seems weird that the three different event types would behave so differently. Why is this? Is there an obvious document out there that I obviously haven't read?
第三次是魅力所在,您可能认为keydown似乎有效,但是使用keydown,您会得到重复键。我知道,您所要做的就是在您第一次被调用时解除绑定处理程序,但是这三种不同的事件类型的行为如此不同似乎很奇怪。为什么是这样?有没有明显的文件我显然没有读过?
回答by Chase
按键:
The keypress event is sent to an element when the browser registers keyboard input. This is similar to the keydown event, except in the case of key repeats. If the user presses and holds a key, a keydown event is triggered once, but separate keypress events are triggered for each inserted character. In addition, modifier keys(such as Shift) trigger keydown events but not keypress events.
当浏览器注册键盘输入时,keypress 事件被发送到一个元素。这类似于 keydown 事件,除了 key repeats 的情况。如果用户按住某个键,则会触发一次keydown 事件,但会为每个插入的字符触发单独的 keypress 事件。此外,修饰键(例如 Shift)会触发 keydown 事件,但不会触发 keypress events。
按键:
The keydown event is sent to an element when the user first presses a key on the keyboard. It can be attached to any element, but the event is only sent to the element that has the focus. Focusable elements can vary between browsers, but form elements can always get focus so are reasonable candidates for this event type.
当用户第一次按下键盘上的一个键时,keydown 事件被发送到一个元素。它可以附加到任何元素,但事件只发送到具有焦点的元素。可聚焦元素可能 因浏览器而异,但表单元素始终可以获得焦点,因此对于这种事件类型来说是合理的候选者。
键盘输入:
The keyup event is sent to an element when the user releases a key on the keyboard. It can be attached to any element, but the event is only sent to the element that has the focus. Focusable elements can vary between browsers, but form elements can always get focus so are reasonable candidates for this event type.
当用户释放键盘上的键时,keyup 事件被发送到一个元素。它可以附加到任何元素,但事件只发送到具有焦点的元素。可聚焦元素可能因浏览器而异,但表单元素始终可以获得焦点,因此对于这种事件类型来说是合理的候选者。
Also, this is a handy piece of information that is usually glossed over:
此外,这是一个方便的信息,通常被掩盖:
If key presses anywhere need to be caught (for example, to implement global shortcut keys on a page), it is useful to attach this behavior to the document object. Because of event bubbling, all key presses will make their way up the DOM to the document object unless explicitly stopped.
To determine which character was entered, examine the event object that is passed to the handler function. While browsers use differing properties to store this information, jQuery normalizes the .whichproperty so you can reliably use it to retrieve the character code.
Note that keydown and keyup provide a code indicating which key is pressed, while keypress indicates which character was entered.For example, a lowercase "a" will be reported as 65 by keydown and keyup, but as 97 by keypress. An uppercase "A" is reported as 65 by all events. Because of this distinction, when catching special keystrokes such as arrow keys, .keydown() or .keyup() is a better choice.
如果需要捕获任何地方的按键操作(例如,要在页面上实现全局快捷键),则将此行为附加到文档对象会很有用。由于事件冒泡,除非明确停止,否则所有按键都会沿 DOM 向上到达文档对象。
要确定输入了哪个字符,请检查传递给处理程序函数的事件对象。虽然浏览器使用不同的属性来存储这些信息,但 jQuery 规范了.which属性,以便您可以可靠地使用它来检索字符代码。
请注意,keydown 和 keyup 提供了一个代码,指示按下了哪个键,而 keypress 则指示输入了哪个字符。例如,小写的“a”将被 keydown 和 keyup 报告为 65,但被 keypress 报告为 97。所有事件都将大写“A”报告为 65。由于这种区别,在捕获特殊击键(例如箭头键)时,.keydown() 或 .keyup() 是更好的选择。
More information regarding the cmd
key on MACs: jQuery key code for command key
有关cmd
MAC上密钥的更多信息:命令密钥的 jQuery 密钥代码
回答by Terry
This articleis a good resource explaining the differences between keyup
, keydown
and keypress
.
这篇文章是一个很好的资源,解释了keyup
、keydown
和之间的区别keypress
。
The short answer is there is no easy way to handle them other than to account for the different browsers.
简短的回答是,除了考虑不同的浏览器之外,没有简单的方法来处理它们。
The way I personally handle it in a Bootstrap plugin I wroteis by creating a custom method to check which event is supported. Coincidentally a very similar method showed up in the official Bootstrap version a little while later :P
我个人在我编写的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;
}
Later on I use it in my code to attach event handlers:
后来我在我的代码中使用它来附加事件处理程序:
if (this.eventSupported('keydown')) {
this.$element.on('keydown', $.proxy(this.keypress, this));
}
回答by o.v.
You have to remember that when validating a KeyboardEvent
on a mac, ?
modifier key will notbe picked up as event.ctrlKey
but rather an event.metaKey
. Further documentation is available on MDN.
你必须记住,在验证时,KeyboardEvent
在Mac上,?
修改键将不会被拾起的event.ctrlKey
,而是一个event.metaKey
。MDN上提供了更多文档。
Without seeing any code, my bet is on this being the reason for ?+Enter
not being picked up.
在没有看到任何代码的情况下,我打赌这是?+Enter
没有被选中的原因。