如何在整个页面上监听按键事件?

166

我正在寻找一种将函数绑定到整个页面的方法(当用户按键时,我希望它会触发component.ts中的一个函数)。

在 AngularJS 中使用 ng-keypress 很容易实现这个功能,但是在 (keypress)="handleInput($event)" 中却行不通。

我尝试使用一个包装整个页面的 div,但似乎无效。 只有在焦点在它上面时才起作用。

<div (keypress)="handleInput($event)" tabindex="1">

你尝试过使用 window:keypress 吗? - KarolDepka
7个回答

294

我会在你的组件中使用@HostListener装饰器:

import { HostListener } from '@angular/core';

@Component({
  ...
})
export class AppComponent {

  @HostListener('document:keypress', ['$event'])
  handleKeyboardEvent(event: KeyboardEvent) { 
    this.key = event.key;
  }
}

还有其他选择,例如:

@Component 装饰器内的 host 属性

Angular 建议使用 @HostListener 装饰器而不是 host 属性。https://angular.io/guide/styleguide#style-06-03

@Component({
  ...
  host: {
    '(document:keypress)': 'handleKeyboardEvent($event)'
  }
})
export class AppComponent {
  handleKeyboardEvent(event: KeyboardEvent) {
    console.log(event);
  }
}

renderer.listen

import { Component, Renderer2 } from '@angular/core';

@Component({
  ...
})
export class AppComponent {
  globalListenFunc: Function;

  constructor(private renderer: Renderer2) {}

  ngOnInit() {
    this.globalListenFunc = this.renderer.listen('document', 'keypress', e => {
      console.log(e);
    });
  }

  ngOnDestroy() {
    // remove listener
    this.globalListenFunc();
  }
}

Observable.fromEvent

import { Observable } from 'rxjs/Observable';
import 'rxjs/add/observable/fromEvent';
import { Subscription } from 'rxjs/Subscription';

@Component({
  ...
})
export class AppComponent {
  subscription: Subscription;

  ngOnInit() {
    this.subscription = Observable.fromEvent(document, 'keypress').subscribe(e => {
      console.log(e);
    })
  }

  ngOnDestroy() {
    this.subscription.unsubscribe();
  }
}

2
运行良好。需要导入{HostListener} from '@angular/core',并在组件中的任何位置调用事件即可。甚至在构造函数之外也可以正常工作。 - gnganapath
33
谢谢您,但是提醒未来的读者:如果您需要箭头键,请使用keydown而不是keypress。 - Troels Larsen
19
如需使用“ESC”键,请使用“keyup”事件。感谢@TroelsLarsen。 - Aron Lorincz
2
@yurzui 我该如何检测“功能键”(F1,F2,F3,...)? - Arpit Kumar
这不会检测“转义”。 - Steinfeld
显示剩余6条评论

25

仅补充一点,在2019年使用Angular 8时,

不再使用keypress而是要使用keydown。

@HostListener('document:keypress', ['$event'])

@HostListener('document:keydown', ['$event'])

使用Stacklitz工作


Angular 9 报告:无论是 keypress 还是 keydown 都可以注册普通的“asdf”键,但只有 keydown 可以获取 F4 和其他功能键。Keypress 可以获取一些键组合,如 CTRL-Z,keydown 将其分别解释(先是 CTRL 键,然后是几毫秒后的 Z 键)。 - Anders8

21

yurzui的答案对我没有用,可能是因为使用了不同的RC版本,或者可能是我的问题。无论如何,下面是我在Angular2 RC4中处理组件的方法(现在已经相当过时)。

@Component({
    ...
    host: {
        '(document:keydown)': 'handleKeyboardEvents($event)'
    }
})
export class MyComponent {
    ...
    handleKeyboardEvents(event: KeyboardEvent) {
        this.key = event.which || event.keyCode;
    }
}

3
就是一样的,只是采用了替代语法,并且你使用了 keydown 而不是 keypress - Günter Zöchbauer
就像我说的那样,可能是我的错误,但这就是让它对我起作用所需要的。 :) - Adam
1
最新的文档建议使用@HostListener:https://angular.io/docs/ts/latest/guide/style-guide.html#!#-a-id-06-03-a-use-hostlistener-and-hostbinding-class-decorators - saschwarz
无法工作!当前上下文中不存在 'key' 属性。 - user2136053
你不能只是复制粘贴代码并期望它在没有修改的情况下工作@ritesh。你需要将key定义为类变量,或更改赋值以分配给局部变量。 - Adam
显示剩余2条评论

6

如果你想在特定的键盘按键按下时执行任何事件,那么可以使用@HostListener。为此,您需要在组件ts文件中导入HostListener。

import { HostListener } from '@angular/core';
然后在组件ts文件中任何位置使用以下函数。

@HostListener('document:keyup', ['$event'])
  handleDeleteKeyboardEvent(event: KeyboardEvent) {
    if(event.key === 'Delete')
    {
      // remove something...
    }
  }

1

1
我在这个问题上有点困惑,所以tshoemake提供了正确的答案,也适用于F键。 为了防止F键执行其原始的浏览器操作,比如搜索,还需要调用preventDefault()方法。
添加以下包含内容。
import { Component, HostListener } from '@angular/core';

并且

@HostListener('document:keydown', ['$event'])
handleTheKeyboardEvent(event: KeyboardEvent) {
    switch (event.key) {
      case "F2":
        this.myF2Action();
        event.preventDefault();
        break;
    }
}

1

我认为这是最好的工作

https://angular.io/api/platform-browser/EventManager

例如,在 app.component 中。
constructor(private eventManager: EventManager) {
    const removeGlobalEventListener = this.eventManager.addGlobalEventListener(
      'document',
      'keypress',
      (ev) => {
        console.log('ev', ev);
      }
    );
  }

2
addGlobalEventListener 已被 @deprecated — 在 Ivy 代码中不再使用。将在版本14中删除。 - Mike de Klerk

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接