原文 - Angular Pseudo-Events 作者 - Shijir Tsogoo
Angular
提供了一个巧妙的小功能,用于简化监听键盘事件的过程。尽管在 Angular
模版绑定文档中提到了伪事件 pseudo-event,但是在其他地方没有进一步的文档说明。深入之前,我们看看 Angular
中的伪事件解决了什么问题。我们简单举个例子,假设你需要添加一个 UNDO
命令来切换复选框。UNDO
命令是恢复用户的上一个选择。
如同我们在自己电脑上执行 UNDO
指令一样,指令应该根据 CTRL Z 组合做出响应。下面的案例展示我们是怎么使用非伪事件实现的:
// app.component.ts
import { Component } from '@angular/core';
@Component({
selector: 'my-app',
templateUrl: 'app.component.html'
})
export class AppComponent {
onKeydown(event: KeyboardEvent) {
if(event.key == "z" && event.ctrlKey) {
event.target.checked = !event.target.checked;
}
}
}
译者加:在 mac 平台上不起效
正如上面案例所示,我们监听 KeyboardEvent.key
来检查哪个按键被敲击。当然,还有很多 KeyboardEvent
的属性可以用来检查和捕获按键,比如 KeyboardEvent.key
, KeyboardEvent.charCode
, KeyboardEvent.keyCode
或者 KeyboardEvent.which
。然而,它们中有些是被抛弃或者浏览器并不支持。并且,我们监听的组合键越多,语法越复杂。
Angular
伪事件将解决上面的担忧。通过伪事件,Angular
允许你直接绑定指定按键或者按键组合。这意味着,键盘事件只会通过特定键或者组合键上触发,而不是所有键盘事件上都触发。如下,是一个关于怎么在模版中声明伪事件的例子:
<input (keyup.enter) ='...responds to enter...' />
<input (keydown.esc) ='...responds to escape...' />
<input (keyup.shift.f) ='...responds to shift f...' />
现在,让我们看看伪事件如何帮助我们监听 CTRL Z
键盘组合:
// app.component.ts
import { Component } from '@angular/core';
@Component({
selector: 'my-app',
templateUrl: 'app.component.html'
})
export class AppComponent {
toggle(checkbox: HTMLElement) {
checkbox.checked = !checkbox.checked;
}
}
正如你所见,我们不再需要检查哪些按键事件被注册,因为我们制定了处理程序的应该响应的组合键,而且语法变得更加声明性。
在 @HostListener 中使用 Pseudo-Events
如同其他 DOM
事件,你可以通过 @HostListener
监听伪事件:
@HostListener('keydown.control.z')
undo(event: KeyboardEvent) {
// responds to control z
}
当然,如果宿主元素不可获取焦点,或者无论事件来自何处,你都要捕获键盘事件,你可以将事件绑定到全局元素,比如:
代码语言:javascript复制@HostListener('document:keydown.control.z')
undo(event: KeyboardEvent) {
// responds to control z
}
Pseudo-Events 的键名
现在,我们看看键组合伪事件的例子:
代码语言:javascript复制<input (keydown.control.shift.z)='...' />
你可能疑惑这些键名(比如: control
, shift
和 z
)来自哪里?它们并不是 Angular
伪元素独有的。实际上,它们是 KeyboardEvent
小写的键属性。如果你想查键盘事件属性值完整的列表,请移步参考。现在,让我们来查看一下可用于 Angular
伪事件的键值。
Modifier Keys
修饰键(Modifier Keys
)包括 Shift
,Control
,Alt(Option)
和 Meta(Command)
。从现在开始,我们会把其他键称为非修饰键。修饰键伪事件的示例如下:
<input (keyup.control)='...respond to ctrl/control...' />
<input (keyup.alt)='...respond to alt/option...' />
<input (keyup.shift)='...respond to shift...' />
<input (keyup.meta)='...respond to command...' />
在 Angular
中使用伪事件,有几个点需要我们记住。
第一,任何组合键都必须有至少一个修饰键,但是只有一个非修饰键。 比如,下面的案例将不会起作用,因为组合键只是由字母组成:
代码语言:javascript复制<input (keyup.a.z)='...responds to a z...' />
第二,非组合键必须放在组合键的最后定义。 下面是一个正确的放置案例,因为非修饰键 Z
放在最后定义:
<input (**keydown.control.z**)='...responds to control z...' />
相比之下,下面这个例子中修饰键放置的位置不对:
代码语言:javascript复制<input (keydown.z.control)='...won't respond at all...' />
第三,修饰键之间的顺序并不影响。 所以,我们可以根据自己的需要放置。下面的案例展示了有效的用例:
代码语言:javascript复制<input (**keydown.shift.control.z**)='...responds to shift control z...' />
<input (**keydown.control.shift.z**)='...responds to control shift z...' />
接下来,我们看看非修饰键的示例。
Functional keys
代码语言:javascript复制<input (keyup.f5)='...responds to F5...' />
<input (keyup.f12)='...responds to F12...' />
Number 和 letter keys
代码语言:javascript复制<input (keyup.0)='...responds to 0...' />
<input (keyup.9)='...responds to 9...' />
<input (keyup.a)='...responds to a...' />
<input (keyup.z)='...responds to z...' />
Arrow keys
代码语言:javascript复制<input (**keyup.arrowup**)='...responds to arrowup...' />
<input (**keyup.arrowright**)='...responds to arrowright...' />
Other keys
代码语言:javascript复制<input (keyup.enter)='...responds to enter...' />
<input (keyup.esc)='...responds to escape...' />
<input (keyup.escape)='...responds to escape...' />
<input (keyup.backspace)='...responds to backspace...' />
<input (keyup.tab)='...responds to tab...' />
到目前,只有两个键没提及:Dot
和 Space
。当你点击 dot
键的时候,KeyboardEvent.key 的属性值是 "."
。但是,我们可以想象下,如果在伪事件中使用点作为分隔符,它在语法上是不正确的。这就是为什么它被映射为 "dot"
关键字。所以,我们需要按照下面的方式正确监听 Dot
按键:
<input (**keydown.dot**)='...responds to dot...'/>
而不是...
代码语言:javascript复制<input (keydown.. )='...won't respond at all...'/>
Space
按键同理。因为它的 KeyboardEvent.key 是空 ""
,映射为 "space"
关键字可读性更高。所以不是这种写法:
<input (keydown. )='...won't respond at all...'/>
而是:
代码语言:javascript复制<input (keydown.space)='...won't respond at all...'/>
不幸的是,Angular
伪事件在大多数字符号键(如减号,等号,斜杆,左括号,右括号,反向号等)上仍然缺乏这种映射。由于它们是符号键,这导致非常差的可读性,有时候会破坏绑定本身。例如,我们想监听 Minus
减号按键,我们只能按照下面这种方式进行:
<input (keydown.-)='...responds to minus...'/>
正如你所见,这看起来很怪异或者语法错误,但是它可行。如果它映射成 "minus"
可读性更高。等号按键呢?
<input (keydown.=)='...breaks the binding...'/>
如果你尝试按照上面的方式监听 Equal
等号按键,它会破坏我们模版绑定,因为它没有与之对应的 "equal"
关键字映射。
尽管符号键存在一些小缺点,但是 Angular
伪事件是一个非常棒的功能,能够满足大多数监听键盘事件的需求。我相信在任何 Angular
应用中使用它可以使实现键盘辅助功能和交互的过程更加简单。
阅读本文后,我希望你已经对 Angular
伪事件有一定的了解。
译者加:某些伪事件在平台上绑定有一定差异,比如在
mac
上绑定document:keydown.control.arrowright
不生效,在window
上则生效