Angular 2键盘事件

23

尝试使用TypeScript和Angular 2来监视键盘事件,但是tslint (codelyzer)在使用“host”属性的"@Component"类装饰器中提出了警告。

使用“host”属性被认为是不良实践,请使用“@HostBindings”、“@HostListeners”属性装饰器。

我该如何使用建议的装饰器? 我不确定Angular 2:Host binding and Host listening中的示例如何适用于我的用例,因为我没有绑定到任何DOM元素。

这是我的演示。

@Component({
  selector: 'my-app',
 template: `
    <div>
      <h2>Keyboard Event demo</h2>
      Start typing to see KeyboardEvent values
    </div>
    <hr />
    KeyboardEvent
    <ul>
      <li>altKey: {{altKey}}</li>
      <li>charCode: {{charCode}}</li>
      <li>code: {{code}}</li>
      <li>ctrlKey: {{ctrlKey}}</li>
      <li>keyCode: {{keyCode}}</li>
      <li>keyIdentifier: {{keyIdentifier}}</li>
      <li>metaKey: {{metaKey}}</li>
      <li>shiftKey: {{shiftKey}}</li>
      <li>timeStamp: {{timeStamp}}</li>
      <li>type: {{type}}</li>
      <li>which: {{which}}</li>
    </ul>
      `,
  host: { '(window:keydown)': 'keyboardInput($event)' }
  /*
  In the "@Component" class decorator you are using the "host" property, this is considered bad practice. 
  Use "@HostBindings", "@HostListeners" property decorator instead.
  */

})
export class App {

  /* a few examples */
  keyboardEvent: any;
  altKey: boolean;
  charCode: number;
  code: string;
  ctrlKey: boolean;
  keyCode: number;
  keyIdentifier: string;
  metaKey: boolean;
  shiftKey: boolean;
  timeStamp: number;
  type: string;
  which: number;

  keyboardInput(event: any) {
    event.preventDefault();
    event.stopPropagation();

    this.keyboardEvent = event;
    this.altKey = event.altKey;
    this.charCode = event.charCode;
    this.code = event.code;
    this.ctrlKey = event.ctrlKey;
    this.keyCode = event.keyCode;
    this.keyIdentifier = event.keyIdentifier;
    this.metaKey = event.metaKey;
    this.shiftKey = event.shiftKey;
    this.timeStamp = event.timeStamp;
    this.type = event.type;
    this.which = event.which;
  }

}

https://plnkr.co/edit/Aubybjbkp7p8FPxqM0zx


FYI -- 上面提到的 Plunker 在 IE 11 中无法正常工作,但在 Chrome 中可以很好地运行。它会卡在“正在加载...”的界面。 - Christopher Hujanen
主机:{'(window:keydown)': 'keyboardInput($event)'}以及keyboardInput(event: any) {}这就是答案,谢谢! - Mark Koorevaar
你可以尝试使用ngxyz-konami - Ankit Singh
2个回答

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

@HostListener('window:keydown', ['$event'])
handleKeyDown(event: KeyboardEvent) {
  // event.key === 'ArrowUp'
}
  • @HostBindings('attr.foo') foo = 'bar' 用于将组件实例中的值绑定到宿主元素上,例如 class、属性、属性或样式。

3
我看到有评论提到使用 host: {} 是不鼓励的,并且推荐使用 @HostBinding()@HostListener(),但是我没有看到 Angular 团队提到过这一点。 - Günter Zöchbauer
我如何为 esc 键执行相同的操作? - user1532043
没有区别。添加 if (event.keyCode == 27) { ... } 来检查事件是否为 esc 键。 - Günter Zöchbauer
1
@GünterZöchbauer,他们已经做到了,请在此处查看:https://angular.io/docs/ts/latest/guide/style-guide.html#!#06-03 - realappie
我也建议你远离host,因为对于键盘事件组合,HostListener对我来说效果更好。 - realappie
1
虽然@HostListener效果很好,但每次按键时它还会使得(我的)Angular变更检测运行在父组件上。使用Observable.fromEvent(window,'keydown').subscribe(...)则不会这样。我猜可以创建一个装饰器,在Angular的zone外运行被装饰的方法,但我还没有尝试过。 - Arjan

1

模板(.html)

<div (keydown)="keyPressed($event)">...</div>

类(.ts)

  keyPressed(keyEvent: KeyboardEvent): void {
    if (keyEvent.key === 'ArrowLeft') {
      console.log('LEFT');
    }
    else if (keyEvent.key === 'ArrowRight') {
      console.log('RIGHT');
    }
  }

放置事件监听器或其任何子元素的元素必须处于焦点状态才能正常工作。要全局捕获,请使用<div (window:keydown)...>

我认为这是更符合 Angular 的方式™,来自docs


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