5

一部のライブラリをカプセル化するコンポーネントがあります。このライブラリのすべてのイベント リスナーの変更検出の悪夢を回避するために、ライブラリは angular ゾーンの外側にスコープが設定されています。

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

  @Output()
  emitter = new EventEmitter<void>();

  constructor(private ngZone: NgZone) {}

  ngOnInit() {
    this.ngZone.runOutsideAngular(() => {
        // ...
    });    
  }

}

それはすべて非常に明確で一般的です。次に、アクションを発行するイベントを追加しましょう。

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

  @Output()
  emitter = new EventEmitter<void>();

  private lib: Lib;

  constructor(private ngZone: NgZone) {}

  ngOnInit() {
    this.ngZone.runOutsideAngular(() => {
      this.lib = new Lib();
    });

    this.lib.on('click', () => {
      this.emitter.emit();
    });
  }

}

問題は、このエミッターがゾーン外でトリガーされるため、変更検出をトリガーしないことです。その場合に可能なことは、ゾーンに再び入ることです。

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

  @Output()
  emitter = new EventEmitter<void>();

  private lib: Lib;

  constructor(private ngZone: NgZone) {}

  ngOnInit() {
    this.ngZone.runOutsideAngular(() => {
      this.lib = new Lib();
    });

    this.lib.on('click', () => {
      this.ngZone.run(() => this.emitter.emit());
    });
  }

}

最後に、私は質問に行きます。this.ngZone.run親コンポーネントでこのイベントをリッスンしていなくても、これにより変更検出が強制されます。

<test-component></test-component>

これは望ましくありません。なぜなら、私はそのイベントをサブスクライブしなかったためです => 検出するものは何もありません。

その問題の解決策は何ですか?

実際の例に興味がある人は、質問の起源はここにあります。

4

2 に答える 2