2017-06-14 80 views
4

我有根組件的一個模板,繪製9瓦:@HostListener原因變化檢測引發過很多次,當我聆聽外面點擊

<ul> 
    <li *ngFor="let x of [0,1,2,3,4,5,6,7,8]"> 
    <tile></tile> 
    </li> 
</ul> 

和明年瓦組件,在那裏我加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 ... 
    } 

} 

Plunker:http://plnkr.co/edit/7wvon25LhXkHQiMcwh48?p=preview

當我運行此我看到每次點擊的變化檢測被稱爲9·2次: enter image description here

我不明白爲什麼。

有人可以向我解釋爲什麼變化檢測在這種情況下會觸發n^2次嗎?

+0

角度補丁所有dom事件偵聽器,所以在調用處理程序角度後將執行更改檢測。你可以使用'zone.runOutsideAngular'來避免它。這可能對你也有幫助https://stackoverflow.com/questions/43108155/angular-2-how-to-keep-event-from-triggering-digest-loop/ 43294113#43294113 – yurzui

+0

看起來它會爲接收事件的每個@HostListener()運行變化檢測。有9個組件實例註冊了點擊事件。每個組件實例都會收到一個單擊事件,然後每次都會爲整個應用運行更改檢測。 我不認爲這種行爲是有道理的,只是我認爲這是發生了什麼。 –

+0

我想了解的是它設計的行爲或錯誤?如果通過設計而不是如何避免使用@HostListener時批量檢測更改觸發。 – Artem

回答

2

簡答 - 這是設計。

由於我們有一個點擊處理程序,角度觸發器會在處理程序被調用後改變檢測。

所以,當第一個組件處理點擊它會導致變化檢測。然後所有組件打印「檢查」。

對於每個組件重複的,所以我有9^2打印「檢查」。

另外還有一點需要注意,OnPush策略無助於減少打印量。