如何根据 Observable 值监听 KeyboardEvent?

问题描述 投票:0回答:1

我是 Angular 新手,并且在 Observables 方面遇到了困难。我搜索了我的问题,但没有找到我的确切问题的答案。 我正在尝试根据从商店获得的变量(可观察)来启用/禁用键盘事件。

...

isDisabled$: Observable<boolean> = this.store.select(selectIsDisabled);

private subscriptions = new Subscription();

constructor(
  private store: Store<IStore>
) {
  this.onKeyboardEvent();
}

...
// this.subscriptions is used in other functions
...

private onKeyboardEvent(): void {
  let keys: string[] = [];
    this.subscriptions.add(
      fromEvent<KeyboardEvent>(document, 'keydown').pipe(
        filter(key => key.repeat === false),
        map(key => key.code)
      ).subscribe(keyCode => {
        if (!keys.includes(keyCode)) {
          keys.push(keyCode);
        }

        // Here we have keys pressed logic...

      })
    );
}

现在这是我的代码,我想要实现的是根据

isDisabled$
值启用/禁用键盘事件(我有一个按钮可以更改 isDisabled$ 值)。

我尝试订阅

isDisabled$
并在 isDisabled 为 false 时调用
this.onKeyboardEvent()
,但问题是这样。即使 isDisabled 为 true,订阅仍然有
fromEvent
事件。

当 isDisabled === true 时,我也尝试取消订阅

this.subscriptions
但这对我不起作用

我是 Angular 和 rxjs 的新手,我不知道是否有运算符可以实现此目的?

感谢您的帮助:)

angular rxjs observable
1个回答
0
投票

你可以像这样尝试

combineLatest

  keyDown$ = fromEvent<KeyboardEvent>(document, 'keydown').pipe(
    map((key) => key.code)
  );
  filteredKeyDown$ = combineLatest([this.isDisabled$, this.keyDown$]).pipe(
    filter(([isDisabled, _]) => !isDisabled),
    map(([_, key]) => key)
  );

如今取消订阅的最佳方法是使用

takeUntilDestroyed

private onKeyboardEvent(): void {
  this.filteredKeyDown$.pipe(takeUntilDestroyed()).subscribe(...);
}

显然我不知道你的确切用例,但也许你可以通过异步管道提供

isDisabled
属性作为输入信号?我不确定我没有测试过这一点。通过这样做,您可以避免处理订阅,这通常是更好的选择。

<app-component [isDisabled]="isDisabled$ | async"/>

...

isDisabled = input.required<boolean>();

@HostListener('document:keydown', ['$event'])
handleKeydown(event: KeyboardEvent) {
  if (this.isDisabled()) return;
  ...
}
© www.soinside.com 2019 - 2024. All rights reserved.