KeyboardEvent: key 属性
KeyboardEvent 接口的只读属性 key 返回用户按下的键的值,该值会考虑修饰键(如 Shift)的状态以及键盘的区域设置和布局。
值
字符串。
其值确定方式如下:
- 如果按下的键具有可打印的表示形式,则返回的值是一个非空的 Unicode 字符字符串,其中包含该键的可打印表示形式。例如:如果按下的键是 Space 键,则返回值是单个空格(
" ")。如果按下的键是 B 键,则返回值是字符串"b"。但是,如果同时按下了 Shift 键(因此shiftKey为true),则返回值是字符串"B"。 - 如果按下的键是控制键或特殊字符,则返回值是 预定义键值 之一。
- 如果
KeyboardEvent表示按下了一个死键,则键值为"Dead"。 - 一些特殊键盘键(例如多媒体键盘上用于控制媒体的扩展键)在 Windows 上不会生成键码;相反,它们会触发
WM_APPCOMMAND事件。这些事件会映射到 DOM 键盘事件,并列在 Windows 的“虚拟键码”中,尽管它们实际上并不是键码。 - 如果无法识别该键,则返回值是
Unidentified。
KeyboardEvent 序列
每个 KeyboardEvent 都是按预定的序列触发的。对于给定的按键操作,假设没有调用 Event.preventDefault,触发的 KeyboardEvent 序列如下:
- 首先会触发一个
keydown事件。如果按键被继续按下并且该键产生一个字符键,则该事件将以平台实现依赖的间隔继续触发,并且KeyboardEvent.repeat只读属性将设置为true。 - 如果该键产生一个字符键,该字符键会插入到可能的
<input>、<textarea>或HTMLElement.contentEditable设置为 true 的元素中,则会按顺序触发beforeinput和input事件类型。请注意,其他一些实现可能会触发keypress事件(如果支持)。当按键被按下时,事件会重复触发。 - 当按键被释放时,会触发一个
keyup事件。这完成了整个过程。
在序列 1 和 3 中,KeyboardEvent.key 属性会被定义并根据前面定义的规则适当地设置为某个值。
KeyboardEvent 序列示例
比较使用美国键盘布局和使用英国键盘布局与 Shift 和 2 键交互时生成的事件序列。
尝试使用以下两个测试用例进行实验:
- 按下并按住 Shift 键,然后按下 2 键并释放它。接下来,释放 Shift 键。
- 按下并按住 Shift 键,然后按下并按住 2 键。释放 Shift 键。最后,释放 2 键。
HTML
<div class="fx">
<div>
<textarea rows="5" name="test-target" id="test-target"></textarea>
<button type="button" name="btn-reset" id="btn-reset">Reset</button>
</div>
<div class="flex">
<pre id="console-log"></pre>
</div>
</div>
CSS
.fx {
-webkit-display: flex;
display: flex;
margin-left: -20px;
margin-right: -20px;
}
.fx > div {
padding-left: 20px;
padding-right: 20px;
}
.fx > div:first-child {
width: 30%;
}
.flex {
-webkit-flex: 1;
flex: 1;
}
#test-target {
display: block;
width: 100%;
margin-bottom: 10px;
}
JavaScript
const textarea = document.getElementById("test-target");
const consoleLog = document.getElementById("console-log");
const btnReset = document.getElementById("btn-reset");
function logMessage(message) {
consoleLog.innerText += `${message}\n`;
}
textarea.addEventListener("keydown", (e) => {
if (!e.repeat) {
logMessage(`Key "${e.key}" pressed [event: keydown]`);
} else {
logMessage(`Key "${e.key}" repeating [event: keydown]`);
}
});
textarea.addEventListener("beforeinput", (e) => {
logMessage(`Key "${e.data}" about to be input [event: beforeinput]`);
});
textarea.addEventListener("input", (e) => {
logMessage(`Key "${e.data}" input [event: input]`);
});
textarea.addEventListener("keyup", (e) => {
logMessage(`Key "${e.key}" released [event: keyup]`);
});
btnReset.addEventListener("click", (e) => {
let child = consoleLog.firstChild;
while (child) {
consoleLog.removeChild(child);
child = consoleLog.firstChild;
}
textarea.value = "";
});
结果
注意: 在不支持 InputEvent 接口(用于 beforeinput 和 input 事件)的浏览器中,日志输出的这些行可能会出现不正确的输出。
情况 1
当按下 Shift 键时,首先会触发 keydown 事件,并且 key 属性值被设置为字符串 Shift。由于我们一直按住该键,因此 keydown 事件不会重复触发,因为它不产生字符键。
当按下 2 键 时,会为这次新的按键触发另一个 keydown 事件,并且由于活动的修饰键 shift,该事件的 key 属性值被设置为字符串 @(适用于美国键盘类型)和 "(适用于英国键盘类型)。接下来会触发 beforeinput 和 input 事件,因为该键产生了一个字符。
当释放 2 键 时,会触发一个 keyup 事件,并且 key 属性将分别保持 @ 和 " 的字符串值,具体取决于键盘布局。
当我们最终释放 shift 键时,会为它触发另一个 keyup 事件,并且 key 属性值将保持为 Shift。
情况 2
当按下 Shift 键时,首先会触发 keydown 事件,并且 key 属性值被设置为字符串 Shift。由于我们一直按住该键,因此 keydown 事件不会重复触发,因为它不产生字符键。
当按下 2 键 时,会为这次新的按键触发另一个 keydown 事件,并且由于活动的修饰键 shift,该事件的 key 属性值被设置为字符串 @(适用于美国键盘类型)和 "(适用于英国键盘类型)。接下来会触发 beforeinput 和 input 事件,因为该键产生了一个字符。当按住该键时,keydown 事件会重复触发,并且 KeyboardEvent.repeat 属性被设置为 true。 beforeinput 和 input 事件也会重复触发。
当我们释放 shift 键时,会为它触发一个 keyup 事件,并且 key 属性值保持为 Shift。此时,请注意,由于修饰键 shift 不再处于活动状态,因此对于重复按下的 2 键 的 keydown 事件,key 属性值现在是 "2"。这同样适用于 beforeinput 和 input 事件的 InputEvent.data 属性。
当我们最终释放 2 键 时,会触发一个 keyup 事件,但 key 属性将被设置为字符串值 2(适用于两种键盘布局),因为修饰键 shift 不再处于活动状态。
示例
此示例使用 EventTarget.addEventListener() 来监听 keydown 事件。当它们发生时,会检查按键的值,看它是否是我们代码感兴趣的按键之一,如果是,则以某种方式处理它(可能是通过控制航天器,或者改变电子表格中的选定单元格)。
window.addEventListener("keydown", (event) => {
if (event.defaultPrevented) {
return; // Do nothing if the event was already processed
}
switch (event.key) {
case "ArrowDown":
// Do something for "down arrow" key press.
break;
case "ArrowUp":
// Do something for "up arrow" key press.
break;
case "ArrowLeft":
// Do something for "left arrow" key press.
break;
case "ArrowRight":
// Do something for "right arrow" key press.
break;
case "Enter":
// Do something for "enter" or "return" key press.
break;
case " ":
// Do something for "space" key press.
break;
case "Escape":
// Do something for "esc" key press.
break;
default:
return; // Quit when this doesn't handle the key event.
}
// Cancel the default action to avoid it being handled twice
event.preventDefault();
});
规范
| 规范 |
|---|
| UI 事件 # dom-keyboardevent-key |
浏览器兼容性
加载中…