KeyboardEvent: key 屬性

Baseline 已廣泛支援

此特性已得到良好確立,可跨多種裝置和瀏覽器版本使用。自 2017 年 3 月起,所有瀏覽器均支援此特性。

KeyboardEvent 介面的只讀屬性 key 返回使用者按下的鍵的值,該值會考慮修飾鍵(如 Shift)的狀態以及鍵盤的區域設定和佈局。

字串。

其值確定方式如下:

  • 如果按下的鍵具有可列印的表示形式,則返回的值是一個非空的 Unicode 字元字串,其中包含該鍵的可打印表示形式。例如:如果按下的鍵是 Space 鍵,則返回值是單個空格(" ")。如果按下的鍵是 B 鍵,則返回值是字串 "b"。但是,如果同時按下了 Shift 鍵(因此 shiftKeytrue),則返回值是字串 "B"
  • 如果按下的鍵是控制鍵或特殊字元,則返回值是 預定義鍵值 之一。
  • 如果 KeyboardEvent 表示按下了一個死鍵,則鍵值為 "Dead"
  • 一些特殊鍵盤鍵(例如多媒體鍵盤上用於控制媒體的擴充套件鍵)在 Windows 上不會生成鍵碼;相反,它們會觸發 WM_APPCOMMAND 事件。這些事件會對映到 DOM 鍵盤事件,並列在 Windows 的“虛擬鍵碼”中,儘管它們實際上並不是鍵碼。
  • 如果無法識別該鍵,則返回值是 Unidentified

KeyboardEvent 序列

每個 KeyboardEvent 都是按預定的序列觸發的。對於給定的按鍵操作,假設沒有呼叫 Event.preventDefault,觸發的 KeyboardEvent 序列如下:

  1. 首先會觸發一個 keydown 事件。如果按鍵被繼續按下並且該鍵產生一個字元鍵,則該事件將以平臺實現依賴的間隔繼續觸發,並且 KeyboardEvent.repeat 只讀屬性將設定為 true
  2. 如果該鍵產生一個字元鍵,該字元鍵會插入到可能的 <input><textarea>HTMLElement.contentEditable 設定為 true 的元素中,則會按順序觸發 beforeinputinput 事件型別。請注意,其他一些實現可能會觸發 keypress 事件(如果支援)。當按鍵被按下時,事件會重複觸發。
  3. 當按鍵被釋放時,會觸發一個 keyup 事件。這完成了整個過程。

在序列 1 和 3 中,KeyboardEvent.key 屬性會被定義並根據前面定義的規則適當地設定為某個值。

KeyboardEvent 序列示例

比較使用美國鍵盤佈局和使用英國鍵盤佈局與 Shift2 鍵互動時生成的事件序列。

嘗試使用以下兩個測試用例進行實驗:

  1. 按下並按住 Shift 鍵,然後按下 2 鍵並釋放它。接下來,釋放 Shift 鍵。
  2. 按下並按住 Shift 鍵,然後按下並按住 2 鍵。釋放 Shift 鍵。最後,釋放 2 鍵。

HTML

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

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

js
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 介面(用於 beforeinputinput 事件)的瀏覽器中,日誌輸出的這些行可能會出現不正確的輸出。

情況 1

當按下 Shift 鍵時,首先會觸發 keydown 事件,並且 key 屬性值被設定為字串 Shift。由於我們一直按住該鍵,因此 keydown 事件不會重複觸發,因為它不產生字元鍵。

當按下 2 鍵 時,會為這次新的按鍵觸發另一個 keydown 事件,並且由於活動的修飾鍵 shift,該事件的 key 屬性值被設定為字串 @(適用於美國鍵盤型別)和 "(適用於英國鍵盤型別)。接下來會觸發 beforeinputinput 事件,因為該鍵產生了一個字元。

當釋放 2 鍵 時,會觸發一個 keyup 事件,並且 key 屬性將分別保持 @" 的字串值,具體取決於鍵盤佈局。

當我們最終釋放 shift 鍵時,會為它觸發另一個 keyup 事件,並且 key 屬性值將保持為 Shift

情況 2

當按下 Shift 鍵時,首先會觸發 keydown 事件,並且 key 屬性值被設定為字串 Shift。由於我們一直按住該鍵,因此 keydown 事件不會重複觸發,因為它不產生字元鍵。

當按下 2 鍵 時,會為這次新的按鍵觸發另一個 keydown 事件,並且由於活動的修飾鍵 shift,該事件的 key 屬性值被設定為字串 @(適用於美國鍵盤型別)和 "(適用於英國鍵盤型別)。接下來會觸發 beforeinputinput 事件,因為該鍵產生了一個字元。當按住該鍵時,keydown 事件會重複觸發,並且 KeyboardEvent.repeat 屬性被設定為 truebeforeinputinput 事件也會重複觸發。

當我們釋放 shift 鍵時,會為它觸發一個 keyup 事件,並且 key 屬性值保持為 Shift。此時,請注意,由於修飾鍵 shift 不再處於活動狀態,因此對於重複按下的 2 鍵 的 keydown 事件,key 屬性值現在是 "2"。這同樣適用於 beforeinputinput 事件的 InputEvent.data 屬性。

當我們最終釋放 2 鍵 時,會觸發一個 keyup 事件,但 key 屬性將被設定為字串值 2(適用於兩種鍵盤佈局),因為修飾鍵 shift 不再處於活動狀態。

示例

此示例使用 EventTarget.addEventListener() 來監聽 keydown 事件。當它們發生時,會檢查按鍵的值,看它是否是我們程式碼感興趣的按鍵之一,如果是,則以某種方式處理它(可能是透過控制航天器,或者改變電子表格中的選定單元格)。

js
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

瀏覽器相容性