2017-07-24 225 views
1

閱讀關於Zone.JS並更改檢測過程,在源代碼中Zone.JS通知Angular關於變化,它通過在所有組件上傳播檢查來從上到下運行第一個組件,但在我的測試中,我有一個不同的行爲。Angular OnPush組件,當觸發事件在視圖中角度強迫markForCheck自動?

檢查我的樣本:

http://plnkr.co/edit/QPHBQ7cYg9JFZr2oVnGZ?p=preview

樣品具有以下結構:

<app-component> 
    <child-component> 
     <grand-child-component> 

他們互相嵌套,他們都沒有@input屬性,所有的人是OnPush,並且它們在視圖中顯示簡單的值,如:

查看:

{{getComponentValue}}

打字稿

value = "app component"; 

get getComponentValue() { // <-- ES6 get to log when Angular check 
    console.log('change detection checking here in component app-component') 
    return this.value; 
} 

可以在樣品中檢查這個代碼。

當應用程序被啓動,我們可以看到日誌:

check component app 
check component child 
check component grand child 

很酷,但是,現在我們如果盛大孩子觸發事件的想象嗎?

在盛大的孩子

<button (click)="undefined"> {{getComponentValue}} </button> 
<!-- (click)="undefined" cria um inscrito no evento. --> 

更改視圖我們有日誌:

check component app 
check component child 
check component grand child 

我預計:當我點擊了盛大子按鈕,該事件將開始在應用程序組件, 但是,由於所有這些都是OnPush,從來沒有事件會到達盛大的孩子,因爲沒有@Input被更改,我將不得不手動調用markforcheck或detectchanges,但上面的代碼看起來像我調用了markforcheck。

我在grand-child組件中調用了settimeout,interval和具有可觀察對象的事件,並且它們都沒有調用更改(檢查grand-component ts),僅在視圖中(單擊)檢查被調用...

驗證發生在你可以測試的地方:在孩子或應用程序組件中,你可以添加setInterval,增加一個值 你可以檢查視圖,認識到只有當grand-child觸發(單擊)你的祖先的價值更新!

我意識到:setTimeout的,間隔,或與觀測組件和的TS內的事件時,該組件是OnPush 事件在應用程序組件啓動,但它們不是「強行傳播」,因爲在沒有變化@Input,但是當我們在視圖中添加事件時,就像(點擊)一些 他們通過模擬markForCheck強制的方式,實際發生了什麼?

當我們在視圖中添加一個事件時,引擎蓋下的Angular強制使用markForCheck();對組件? 因爲這似乎是發生。

回答

2

是的,這是由設計:一個綁定的事件triggers markForCheck內部

export function dispatchEvent(
    view: ViewData, nodeIndex: number, eventName: string, event: any): boolean { 
    const nodeDef = view.def.nodes[nodeIndex]; 
    const startView = 
     nodeDef.flags & NodeFlags.ComponentView ? asElementData(view, nodeIndex).componentView : view; 
    markParentViewsForCheck(startView); // <== this line 
    return Services.handleEvent(view, nodeIndex, eventName, event); 
} 

參見

+0

謝謝你的回覆!很酷,在你的鏈接中,你說過4個用OnPush調用檢測的情況,但是你還沒有忘記detectChanges()?這會引發他和他的孩子的變化,對嗎? –

+0

@GustavoCosta它不會觸發onPush策略的變化。 https://plnkr.co/edit/O65ZZ8147J6eDVjreXaO?p=preview – yurzui

+0

使用detectChanges,檢查僅在組件中使用綁定進行,並且您的子項和@Input屬性將不會被檢查,是嗎? –