Angular @当I';我在听外面的声音

Angular @当I';我在听外面的声音,angular,angular2-changedetection,Angular,Angular2 Changedetection,我有根组件的下一个模板,它绘制了9个平铺: <ul> <li *ngFor="let x of [0,1,2,3,4,5,6,7,8]"> <tile></tile> </li> </ul> 下一个tile组件,我在其中添加了用于文档单击的HostListener: import {AfterViewChecked, Component, HostListener} from '@angular/

我有根组件的下一个模板,它绘制了9个平铺:

<ul>
  <li *ngFor="let x of [0,1,2,3,4,5,6,7,8]">
    <tile></tile>
  </li>
</ul>
下一个tile组件,我在其中添加了用于文档单击的HostListener:

import {AfterViewChecked, Component, HostListener} from '@angular/core';

@Component({
  selector: 'tile',
  template: '<p>tile works!</p>'
})
export class TileComponent implements AfterViewChecked {

  ngAfterViewChecked(): void {
    console.log('checked');
  }

  @HostListener('document:click', ['$event'])
  onOutsideClick(event: any): void {
      // do nothing ...
  }

}
从'@angular/core'导入{AfterViewChecked,Component,HostListener};
@组成部分({
选择器:'tile',
模板:“平铺有效!

” }) 导出类TileComponent实现AfterViewChecked{ ngAfterViewChecked():void{ console.log('checked'); } @HostListener('文档:单击',['$event'])) onOutsideClick(事件:任意):无效{ //什么也不做。。。 } }
普朗克:

当我运行此程序时,我发现每次单击时,都会调用9^2次更改检测:

我不明白为什么


有人能给我解释一下为什么在这种情况下更改检测会触发n^2次吗?

简单回答-这是设计的

因为我们有一个点击处理程序,所以在调用处理程序后,角度触发器会改变检测

因此,当第一个组件处理时,单击它将导致更改检测。然后所有组件都打印“选中”

每个组件都重复了这个过程,所以我已经检查了9^2个打印


另外需要注意的是,OnPush策略无助于减少打印量。

@Hostlistener可能成本高昂。在这里检查我的答案,以最小化影响并提高性能。

Angular修补了所有dom事件侦听器,因此在调用处理程序Angular后,将执行更改检测。您可以使用
zone.runOutsideAngular
来避免此问题,这也有助于您看起来它会对每个接收到事件的
@HostListener()
运行更改检测。有9个组件实例注册了click事件。每个组件实例都会收到一个单击事件,然后每次都会对整个应用程序运行更改检测。我并不是说这种行为是有意义的,只是我认为这就是正在发生的事情。我试图理解它是被设计的行为还是bug?如果这是出于设计考虑,那么在使用@HostListener时,如何避免批量检测更改触发是出于设计考虑的。