Làm thế nào tôi có thể nghe sự kiện nhấn phím trên toàn bộ trang?


109

Tôi đang tìm cách liên kết một hàm với toàn bộ trang của mình (khi người dùng nhấn một phím, tôi muốn nó kích hoạt một hàm trong component của mình.

Nó rất dễ dàng trong AngularJS với một ng-keypressnhưng nó không hoạt động với (keypress)="handleInput($event)".

Tôi đã thử nó với một trình bao bọc div trên toàn bộ trang nhưng nó dường như không hoạt động. nó chỉ hoạt động khi tập trung vào nó.

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

Bạn đã thử window:keypresschưa?
KarolDepka

Câu trả lời:


203

Tôi sẽ sử dụng trình trang trí @HostListener trong thành phần của bạn:

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

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

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

Ngoài ra còn có các tùy chọn khác như:

lưu trữ tài sản trong @Componentdecorator

Angular khuyên bạn nên sử dụng @HostListenerdecorator trên thuộc tính máy chủ 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
Hoạt động tốt. nhập {HostListener} từ '@ angle / core' phải thêm. và gọi ngay cả ở bất kỳ đâu trong thành phần. Thậm chí ra contructor bên cũng làm việc tốt
gnganpath

23
Cảm ơn vì điều này, nhưng xin lưu ý những người đọc trong tương lai: nếu bạn cần các phím mũi tên, hãy sử dụng phím xuống thay vì nhấn phím.
Troels Larsen

14
Nếu bạn cần esckhóa, hãy sử dụng keyupsự kiện. Nhờ @TroelsLarsen
Aron Lorincz

@yurzui, làm cách nào để tôi có thể sử dụng sự kiện này cho component.not cụ thể trên toàn bộ trang
kamalav

1
@yurzui Làm cách nào để phát hiện a function-key(F1, F2, F3, ...)?
Arpit Kumar

18

Câu trả lời của yurzui không phù hợp với tôi, nó có thể là một phiên bản RC khác, hoặc có thể do lỗi của tôi. Dù bằng cách nào, đây là cách tôi đã làm điều đó với thành phần của tôi trong Angular2 RC4 (hiện đã khá lỗi thời).

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

3
Đó là giống nhau, cú pháp chỉ thay thế và bạn đã sử keydownthay vìkeypress
Günter Zöchbauer

Như tôi đã nói, có lẽ là một sai lầm từ phía tôi, nhưng đó là điều tôi cần làm để làm cho nó hoạt động. :)
Adam

Lợi ích của việc này so với sử dụng document.addEventListener là gì? Nó chỉ là một vấn đề trừu tượng hóa DOM?
Ixonal

@Ixonal # 2 trong bài viết này mô tả tốt hơn những gì tôi có thể: anglejs.blogspot.ca/2016/04/… Về cơ bản, nó không phải là cách 'Angular', vì nó được kết hợp với trình duyệt và không thể kiểm tra được. Có thể bây giờ không phải là một vấn đề lớn, nhưng đó là một mô hình tốt để làm theo.
Adam

1
Các tài liệu mới nhất khuyên bạn sử dụng @HostListener: angular.io/docs/ts/latest/guide/...
saschwarz

11

Chỉ để thêm vào điều này vào năm 2019 với Angular 8,

thay vì nhấn phím tôi phải sử dụng phím xuống

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

đến

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

Làm việc Stacklitz


Báo cáo Angular 9: cả nhấn phím và nhấn phím xuống sẽ đăng ký các phím "asdf" bình thường, nhưng chỉ nhấn phím xuống mới nhận được F4 và các phím chức năng khác. Nhấn phím có thể nhận được một số tổ hợp phím như CTRL-Z, việc nhấn phím sẽ diễn giải các tổ hợp đó một cách riêng biệt (phím CTRL, sau đó đến mili giây, phím Z).
Anders

4

Nếu bạn muốn thực hiện bất kỳ sự kiện nào trên bất kỳ lần nhấn nút bàn phím cụ thể nào, trong trường hợp đó, bạn có thể sử dụng @HostListener. Đối với điều này, bạn phải nhập HostListener trong tệp ts thành phần của mình.

nhập {HostListener} từ '@ angle / core';
sau đó sử dụng hàm dưới đây ở bất kỳ đâu trong tệp ts thành phần của bạn.

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


0

Tôi nghĩ điều này làm công việc tốt nhất

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

ví dụ trong app.component

constructor(private eventManager: EventManager) {
    const removeGlobalEventListener = this.eventManager.addGlobalEventListener(
      'document',
      'keypress',
      (ev) => {
        console.log('ev', ev);
      }
    );
  }
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.