【问题标题】:Angular HTML Binding is not working when we removed HostListener当我们删除 HostListener 时,Angular HTML 绑定不起作用
【发布时间】:2021-09-18 03:37:43
【问题描述】:

为了减少变更检测,我们将 hostlistener 替换为来自 RXJS 的事件和 angular 的 runoutside。

这就是我的角度代码的样子

ngOnInit() {
    this.windowKeyDown();
    // this.subject$ = this.subject.asObservable();
  }

  constructor(private _ngZone: NgZone) {}

  //@HostListener('window:keydown', ['$event'])
  handleKeyboardEvent(event: KeyboardEvent) {
    console.log('handle key fired');
    this.keypressed = event.key;
    this.iskeyPressed = true;
  }

  windowKeyDown() {
    console.log('windowKeyDown');
    fromEvent(window, 'keydown')
      .pipe(this.outsideZone(this._ngZone))
      .subscribe(event => this.handleKeyboardEvent(<KeyboardEvent>event));
  }

  outsideZone<T>(zone: NgZone) {
    return function(source: Observable<T>) {
      return new Observable(observer => {
        let sub: Subscription;
        zone.runOutsideAngular(() => {
          sub = source.subscribe(observer);
        });

        return sub;
      });
    };
  }

和 HTML 绑定是:

<h2>keypressed: {{keypressed}}</h2>
<h2>iskeyPressed: {{iskeyPressed}}</h2>

在这个绑定变量中它自己现在没有更新,你能指导一下我的代码有什么问题吗?

重现的最小步骤:https://stackblitz.com/edit/keypress-example-vu3mej?file=app%2Fapp.component.html

【问题讨论】:

    标签: javascript angular rxjs angular2-template


    【解决方案1】:

    我建议将此组件的 ChangeDetectionStrategy 设置为 OnPush。你可以阅读更多关于它的信息here。不要在此组件中放置任何您希望自动更改检测的逻辑,因为整个组件都禁用了更改检测。

    下面是一个代码示例,展示了如何直接从模板订阅键盘事件(使用异步管道)。

    https://stackblitz.com/edit/angular-change-detection-strategy-onpush-g6mjkr?file=src%2Fapp%2Fchild%2Fchild.component.ts

    import {
      Component,
      Input,
      ChangeDetectionStrategy,
      OnInit
    } from '@angular/core';
    import { fromEvent, Observable } from 'rxjs';
    import { map, startWith, tap } from 'rxjs/operators';
    
    @Component({
      selector: 'child',
      template: `
        <ng-container *ngIf="keyboard$ | async as keyBoard">
          <h2>keypressed: {{ keyBoard.keypressed }}</h2>
          <h2>iskeyPressed: {{ keyBoard.iskeyPressed }}</h2>
        </ng-container>
      `,
      styleUrls: [],
      changeDetection: ChangeDetectionStrategy.OnPush
    })
    export class ChildComponent implements OnInit {
      keyboard$: Observable<{ keypressed: any; iskeyPressed: boolean }>;
      ngOnInit() {
        console.log('bla')
        this.keyboard$ = fromEvent(window, 'keydown').pipe(
          map(event => ({ keypressed: event.key, iskeyPressed: true })),
          startWith({keypressed: null, iskeyPressed: null})
        );
      }
    }
    

    【讨论】:

    • 谢谢,我会尝试这个解决方案并接受答案。
    猜你喜欢
    • 2021-04-07
    • 2017-09-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-06-16
    相关资源
    最近更新 更多