2017-04-30 84 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分支时,它可能会抛出错误。无论是切换到“公共”或创建一个公共只读功能,如我的示例 –