2017-04-30 83 views
0

據我所知,如果輸入屬性更改(也有其他方式),則更改檢測將觸發OnPush標記的組件。角2更改檢測:OnPush

但我沒有在我的子組件輸入屬性,我有一個服務注入到我的組件。我訂閱了這個子組件中服務所暴露的observable。現在在訂閱回調方法中,我更改了我的子組件的私有屬性值中的一個。該組件的模板與此屬性綁定。

所以問題是當觀察者發佈一個事件時,我的訂閱者回調被調用,並且它改變了屬性值,但是這個視圖並不反映這些改變。用戶界面只在我點擊頁面某處時更新。

changeDetection: ChangeDetectionStrategy.OnPush 

更新1:Plunker添加

+0

你試過使用異步管道或'cdRef.markForCheck()'?你的代碼在哪裏? – yurzui

+0

我無法使用異步管道,因爲我的模板綁定到組件示例字符串的私有屬性。和CDR.markForCheck()我讀過,但不是一個矯枉過正,因爲它會通過發射CD回到anscetor根組件?我不知道如何發佈一個重要的,將谷歌和不久之後添加。謝謝。 – thinkmmk

+0

不,'markForCheck'不會回到祖先的根。這是'ApplicationRef.tick()'。 'markForCheck'使得組件在下一次變化檢測輪迴時不被跳過。 –

回答

1

因此,意見是完全正確的。如果您的應用程序去markForCheck()將導致其上升到根,但是這並不是一件壞事..

root > section > page > area > row > list和您在您list變化,那麼你會想通知的改變已經發生的父項。也許你現在需要增加更多的數據,或者觸發滾動或者各種各樣的東西。

但請記住,你必須等待打勾,如果你使用的父母onPush()也沒有被告知孩子已經與markForCheck()改變檢測將永遠達不到你的孩子,這就是爲什麼它去一路。

另一種方法是用手動觸發detectChanges()這將只對本地組件運行,並把那個叫detectChanges()作爲根節點..

另外,如果你顯示你的組件的任何屬性它不是技術上來說是私人的。 Javascript當然會允許它,但測試套件,我認爲即使編譯器會抱怨。如果你爲什麼必須這樣做,顯示它與公共getter ..像這樣:

Private _mySuperSecret: 'I am Batman'; 
Public get mySecret() { return this._mySuperSecret; }; 
+0

我編輯了我的問題來添加plunker。當我使用detectChanges()時它也可以工作,但在我無法分享的實際代碼中,detectChanges()不起作用。但是markForChanges()起作用。我正在使用角度2.4.0版本。我也不明白你答案的第三段,你能幫我理解一下嗎?我現在對我的應用程序的行爲感到困惑。 – thinkmmk

+0

是的,這句話有點糟糕。我的意思是說,你有一個父組件(A),它是'onPush()'和一個孩子(B),它是'onPush()',又一個孩子(C)是'onPush()',這個是您觸發更改的地方。無論檢測器是以**根**開頭還是說「你有變化嗎?」,markForCheck()的原因都是從根到樹。如果沒有,它會跳過它,並且C子上的更改將永遠不會被檢測到。因此,他們標記所有要測試的父母,以便實際更改的孩子將被檢測到並更新 –

+0

如果您的意思是關於「私人」的事情,則「私人」是爲內部數據保留的。通常不以任何方式暴露它,包括組件的視圖層。 Javascript當然不在乎,但是Typescript可以和Angular Compiler一樣。當你移動到當前的4.X分支時,它可能會拋出錯誤。無論是切換到「公共」或創建一個公共只讀功能,如我的示例 –