aboutsummaryrefslogtreecommitdiff
path: root/files/zh-cn/web/api/keyboardevent/key/index.html
blob: 617cc4f7b99a44ad7500e702e37c61790e74cde7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
---
title: KeyboardEvent.key
slug: Web/API/KeyboardEvent/key
tags:
  - 参考
  - 只读属性
  - 属性
  - 键盘事件
translation_of: Web/API/KeyboardEvent/key
---
<p>{{APIRef("DOM Events")}}</p>

<p><span class="seoSummary">只读属性 <strong><code>KeyboardEvent.key</code></strong> 返回用户按下的物理按键的值。它还与 <code>shiftKey</code> 等调节性按键的状态和键盘的区域 / 和布局有关。</span>它的值由以下因素决定:</p>

<div class="pull-aside">
<p class="moreinfo">查看 <a href="/docs/Web/API/KeyboardEvent/key/Key_Values">所有键值列表</a></p>
</div>

<ul>
 <li>如果按下的键拥有可打印的内容,则返回一个非空的 Unicode 字符来代表这个键的可打印内容。</li>
 <li>如果按下的键是一个控制键或特殊字符,则返回一个事先定义好的值,见<a href="/zh-CN/docs/Web/API/KeyboardEvent/key/Key_Values">预定义键值列表</a></li>
 <li>如果 <code>KeyboardEvent</code> 显示按下的键是一个死键(dead key),则键值为 <code>"Dead"</code></li>
 <li>有些特殊键盘的键(比如多媒体键盘上用来控制媒体播放的扩展按键)在 Windows 下会触发 <code>WM_APPCOMMAND</code> 事件,而不会产生按键代码。虽然没有按键代码,这些事件将映射到 DOM 键盘事件中,并将列入 Windows 的“虚拟按键码”列表中。</li>
 <li>如果按键无法识别,则返回 <code>"Unidentified"</code></li>
</ul>

<h2 id="KeyboardEvent_次序">KeyboardEvent 次序</h2>

<p><code>KeyboardEvent</code> 事件以一个预设的次序触发,理解这一点对于理解特定 <code>KeyboardEvent</code><code>key</code> 属性值大有帮助。对于一个给定的按键操作,<code>KeyboardEvent</code> 将假定 {{domxref("Event.preventDefault")}} 未调用并按下面次序触发:</p>

<ol>
 <li>首先触发 {{event("keydown")}} 事件。如果按键长按且生成一个字符,则事件将以一个与平台实现方式相关的时间间隔持续发出,同时将只读属性 {{domxref("KeyboardEvent.repeat")}} 设定为 <code>true</code></li>
 <li>如果按键生成的字符即将插入某个 {{HTMLElement("input")}}、{{HTMLElement("textarea")}} 或其它某个 {{domxref("HTMLElement.contentEditable")}} 设为 true 的元素,则依次触发 {{event("beforeinput")}}、{{event("input")}}事件。注意某些实现中若支持 {{event("keypress")}} 事件则可能将其触发。当按键长按时重复触发。</li>
 <li>当按键松开时触发 {{event("keyup")}} 事件。操作结束。</li>
</ol>

<p>在次序1、3中,<code>KeyboardEvent.key</code> 属性按照事先定义的规则设定为恰当的值。</p>

<h2 id="KeyboardEvent_次序示例">KeyboardEvent 次序示例</h2>

<p>考虑使用美国或英国键盘布局生成的点击 <code>shiftKey</code> 和一个未知的 <code>key 2</code> 时的事件次序。</p>

<p>请检测以下两个测试用例:</p>

<ol>
 <li>按下并长按 <code>shift</code> 键,然后按下 <code>key 2</code> 并松开。下一步,松开 <code>shift</code> 键。</li>
 <li>按下并长按 <code>shift</code> 键,然后按下并长按 <code>key 2</code>。然后松开 shift 键,最后松开 <code>key 2</code></li>
</ol>

<h3 id="HTML">HTML</h3>

<pre class="brush: html">&lt;div class="flex flex-left"&gt;
    &lt;textarea rows="5" id="test-target"&gt;&lt;/textarea&gt;
    &lt;button id="btn-clear-console"&gt;清空控制台&lt;/button&gt;
&lt;/div&gt;
&lt;div class="flex flex-right"&gt;
    &lt;div id="console-log"&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;script src="main.js"&gt;&lt;/script&gt;</pre>

<h3 id="CSS">CSS</h3>

<pre class="brush: css">body {
    -webkit-display: flex;
    display: flex;
}

.flex {
    padding-left: 20px;
    padding-right: 20px;
}

.flex-left {
    flex: 1;
    flex-grow: 1;
    -webkit-flex: 1;
    -webkit-flex-grow: 1;
}

.flex-right {
    flex: 2;
    flex-grow: 2;
    -webkit-flex: 2;
    -webkit-flex-grow: 2;
}

#test-target {
    display: block;
    width: 100%;
    margin-bottom: 10px;
    resize: none;
}

#console-log {
    overflow: auto;
}</pre>

<h3 id="JavaScript">JavaScript</h3>

<pre class="brush: js">let textarea = document.getElementById('test-target'),
consoleLog = document.getElementById('console-log'),
btnClearConsole = document.getElementById('btn-clear-console');

function logMessage(message) {
  let p = document.createElement('p');
  p.appendChild(document.createTextNode(message));
  consoleLog.appendChild(p);
}

textarea.addEventListener('keydown', (e) =&gt; {
  if (!e.repeat)
    logMessage(`第一个 keydown 事件。key 属性的值为"${e.key}"`);
  else
    logMessage(`keydown 事件重复。key 属性的值为"${e.key}"`);
});

textarea.addEventListener('beforeinput', (e) =&gt; {
  logMessage(`beforeinput 事件。你准备输入"${e.data}"`);
});

textarea.addEventListener('input', (e) =&gt; {
  logMessage(`input 事件。你刚刚输入了"${e.data}"`);
});

textarea.addEventListener('keyup', (e) =&gt; {
  logMessage(`keyup 事件。key 属性的值为"${e.key}"`);
});

btnClearConsole.addEventListener('click', (e) =&gt; {
  let child = consoleLog.firstChild;
  while (child) {
   consoleLog.removeChild(child);
   child = consoleLog.firstChild;
  }
});</pre>

<h3 id="运行结果">运行结果</h3>

<div class="hidden">
<h6 id="Key">Key</h6>

<pre class="brush: html">&lt;!DOCTYPE html&gt;
&lt;html lang="zh-CN"&gt;
&lt;head&gt;
    &lt;meta charset="UTF-8"&gt;
    &lt;style&gt;
    body { -webkit-display: flex; display: flex; }
    .flex { padding-left: 20px; padding-right: 20px; }
    .flex-left { flex: 1; flex-grow: 1; -webkit-flex: 1; -webkit-flex-grow: 1; }
    .flex-right { flex: 2; flex-grow: 2; -webkit-flex: 2; -webkit-flex-grow: 2; }
    #test-target { display: block; width: 100%; margin-bottom: 10px; resize: none; }
    #console-log { overflow: auto; }
    &lt;/style&gt;
    &lt;title&gt;KeyboardEvent.key&lt;/title&gt;
&lt;/head&gt;

&lt;body&gt;
    &lt;div class="flex flex-left"&gt;
        &lt;textarea rows="5" id="test-target"&gt;&lt;/textarea&gt;
        &lt;button id="btn-clear-console"&gt;清空控制台&lt;/button&gt;
    &lt;/div&gt;
    &lt;div class="flex flex-right"&gt;
        &lt;div id="console-log"&gt;&lt;/div&gt;
    &lt;/div&gt;
    &lt;script&gt;
    let textarea = document.getElementById('test-target'),
    consoleLog = document.getElementById('console-log'),
    btnClearConsole = document.getElementById('btn-clear-console');

    function logMessage(message) {
        let p = document.createElement('p');
        p.appendChild(document.createTextNode(message));
        consoleLog.appendChild(p);
    }

    textarea.addEventListener('keydown', (e) =&gt; {
        if (!e.repeat)
            logMessage(`第一个 keydown 事件。key 属性的值为"${e.key}"`);
        else
            logMessage(`keydown 事件重复。key 属性的值为"${e.key}"`);
    });

    textarea.addEventListener('beforeinput', (e) =&gt; {
        logMessage(`beforeinput 事件。你准备输入"${e.data}"`);
    });

    textarea.addEventListener('input', (e) =&gt; {
        logMessage(`input 事件。你刚刚输入了"${e.data}"`);
    });

    textarea.addEventListener('keyup', (e) =&gt; {
        logMessage(`keyup 事件。key 属性的值为"${e.key}"`);
    });


    btnClearConsole.addEventListener('click', (e) =&gt; {
        let child = consoleLog.firstChild;
        while (child) {
            consoleLog.removeChild(child);
            child = consoleLog.firstChild;
        }
    });
    &lt;/script&gt;
&lt;/body&gt;
&lt;/html&gt;</pre>
</div>

<p>{{ EmbedLiveSample('Key', '100%', 480, "", "", "hide-codepen-jsfiddle") }}</p>

<h3 id="用例_1">用例 1</h3>

<p>当按下 shift 键时,首先触发 {{event("keydown")}} 事件,然后将 <code>key</code> 属性的值设为 <code>"Shift"</code> 字符串。如果继续长按 shift 键,由于不会生成字符按键值,{{event("keydown")}} 事件不会继续重复触发。</p>

<p>当按下 <code>key 2</code> 时,另一个 {{event("keydown")}} 事件将会为这个新的按键动作触发,若使用的是美式键盘,它的 <code>key</code> 属性将被设为 <code>"@"</code> 字符,若为英式键盘,则会设为 <code>"""</code> 字符。这是因为 <code>key</code> 属性 <code>"shift"</code> 处于激活状态。由于生成了一个字符的按键值,{{event("beforeinput")}} 和 {{event("input")}} 事件随后触发。</p>

<p>松开 <code>key 2</code> 时,{{event("keyup")}} 事件将触发,<code>key</code> 属性将会为不同键盘布局设定合适的字符值,比如 <code>"@"</code><code>"""</code></p>

<p>最后在松开 shift 键时,另一个 {{event("keyup")}} 事件触发,<code>key</code> 值将保持 <code>"Shift"</code> 不变。</p>

<h3 id="用例_2">用例 2</h3>

<p>当按下 shift 键时,首先触发 {{event("keydown")}} 事件,然后将 <code>key</code> 属性的值设为 <code>"Shift"</code> 字符串。如果继续长按 shift 键,由于不会生成字符按键值,{{event("keydown")}} 事件不会继续重复触发。</p>

<p>当按下 <code>key 2</code> 时,另一个 {{event("keydown")}} 事件将会为这个新的按键动作触发,若使用的是美式键盘,它的 <code>key</code> 属性将被设为 <code>"@"</code> 字符,若为英式键盘,则会设为 <code>"""</code> 字符。这是因上档键处于激活状态。由于生成了一个字符的按键值,{{event("beforeinput")}} 和 {{event("input")}} 事件随后触发。如果继续长按 <code>2</code> 键,则 {{event("keydown")}} 事件将持续重复触发,同时将 {{domxref("KeyboardEvent.repeat")}} 属性设置为 <code>true</code>。{{event("beforeinput")}} 和 {{event("input")}} 事件也将持续重复触发。</p>

<p>当松开 shift 键时,{{event("keyup")}} 事件随之触发,且 <code>key</code> 属性保留为 <code>"Shift"</code>。此时请注意为  <code>key 2</code> 长按触发的重复 <code>keydown</code> 事件的 <code>key</code> 值会变成 <code>"2"</code>,因为上档键不再处于激活状态。{{event("beforeinput")}} 与 {{event("input")}} 事件的 {{domxref("InputEvent.data")}} 属性同理。</p>

<p>最终 <code>key 2</code> 松开,{{event("keyup")}} 事件触发,但两种键盘布局的 <code>key</code> 属性均为 <code>"2"</code>。就是因为没有激活上档键。</p>



<h2 id="示例"><font face="x-locale-heading-primary, zillaslab, Palatino, Palatino Linotype, x-locale-heading-secondary, serif"><span style="font-size: 37.33327865600586px;"><strong>示例</strong></span></font></h2>

<p>这个示例使用 {{domxref("EventTarget.addEventListener()")}} 监听 {{event("keydown")}} 事件。当我们事件触发时,将检测按键的值是否为代码所关注,如果是,就进行某项操作。(可能是给飞船转向,或者是调整电子表格中选中单元格的位置。)</p>

<pre class="brush: js">window.addEventListener("keydown", function (event) {
  if (event.defaultPrevented) {
    return; // 如果事件已经在进行中,则不做任何事。
  }

  switch (event.key) {
    case "ArrowUp":
      // 按“↑”方向键时要做的事。
      break;
    case "ArrowDown":
      // 按“↓”方向键时要做的事。
      break;
    case "ArrowLeft":
      // 按“←”方向键时要做的事。
      break;
    case "ArrowRight":
      // 按“→”方向键时要做的事。
      break;
    case "Enter":
      // 按“回车”键时要做的事。
      break;
    case "Escape":
      // 按“ESC”键时要做的事。
      break;
    default:
      return; // 什么都没按就退出吧。
  }

  // 取消默认动作,从而避免处理两次。
  event.preventDefault();
}, true);
</pre>

<p><font face="x-locale-heading-primary, zillaslab, Palatino, Palatino Linotype, x-locale-heading-secondary, serif"><span style="font-size: 37.33327865600586px;"><strong>标准</strong></span></font></p>



<table class="standard-table">
 <tbody>
  <tr>
   <th scope="col">标准</th>
   <th scope="col">状态</th>
   <th scope="col">备注</th>
  </tr>
  <tr>
   <td>{{SpecName('DOM3 Events', '#widl-KeyboardEvent-key', 'KeyboardEvent.key')}}</td>
   <td>{{Spec2('DOM3 Events')}}</td>
   <td>初次定义,包括按键的值。</td>
  </tr>
 </tbody>
</table>



<h2 id="兼容性">兼容性</h2>

<p>{{Compat("api.KeyboardEvent.key")}}</p>