【问题标题】:Angular 2 Change detection: OnPushAngular 2 变更检测:OnPush
【发布时间】:2017-09-28 09:08:53
【问题描述】:

我知道如果输入属性发生变化(还有其他方式),则会为 OnPush 标记的组件触发变化检测。

但是我的子组件中没有输入属性,并且我的组件中注入了一个服务。我已经订阅了这个子组件内的服务公开的 observable。现在在订阅回调方法中,我更改了我的子组件的私有属性之一的值。组件的模板与此属性绑定。

所以问题是当观察者发布一个事件时,我的订阅者回调被调用,它改变了属性值,但视图没有反映这些变化。仅当我单击页面中的某个位置时,UI 才会更新。

changeDetection: ChangeDetectionStrategy.OnPush

更新 1:添加了Plunker

【问题讨论】:

  • 您是否尝试过使用异步管道或cdRef.markForCheck()?你的代码在哪里?
  • 我不能使用异步管道,因为我的模板绑定到组件的私有属性,例如字符串。我读过 CDR.markForCheck() ,但这不是矫枉过正,因为它会通过触发 CD 回到祖先根组件?我不知道如何发布一个plunker,将谷歌并很快添加。谢谢。
  • 不,markForCheck 不会回到祖先根。那是ApplicationRef.tick()markForCheck 使组件在下一个更改检测轮次中不被跳过。
  • 实际上我经历了这个,答案的最后一段说它会一直触发到 root stackoverflow.com/questions/35386822/…
  • 不要绑定到私有属性 - 它不兼容 AOT。

标签: angular angular2-changedetection


【解决方案1】:

所以,cmets 是完全正确的。 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; };

【讨论】:

  • 我已经编辑了我的问题以添加 plunker。当我使用 detectChanges() 时,它也在采摘器中起作用,但在我无法共享的实际代码中,detectChanges() 不起作用。但是 markForChanges() 有效。我正在使用 Angular 2.4.0 版本。另外我不明白你答案的第3段,你能帮我理解一下吗?我现在对我的应用程序的行为感到困惑。
  • 是的,这句话有点糟糕。我的意思是说你有一个父组件(A)是onPush()和一个子组件(B)是onPush(),它又有一个子组件(C)是onPush(),这就是你触发更改的地方. markForCheck() 的原因是无论检测器从 root 开始并说“你有更改吗?”如果没有,它会跳过它,并且永远不会检测到子 C 上的更改。因此,他们标记所有要测试的父母,以便检测和更新实际更改的孩子
  • 如果您的意思是 private 事物,private 保留用于内部数据。通常不赞成以任何方式公开它,包括组件的视图层。 Javascript 当然不在乎,但 Typescript 可以,Angular 编译器也可以。当您移动到当前的 4.X 分支时,它可能会抛出错误。要么将其切换到public,要么像我的示例一样创建一个公共只读函数
  • 感谢您的解释。 markForChanges() 在我的代码中有效,但不检测更改()。任何你能想到的理由。因为上面的图片代码适用于两者,但在我的实际代码中只有 markForChanges () 有效。
猜你喜欢
  • 1970-01-01
  • 2017-06-07
  • 2017-08-08
  • 1970-01-01
  • 1970-01-01
  • 2017-06-15
  • 1970-01-01
  • 2017-02-02
  • 2017-05-25
相关资源
最近更新 更多