【发布时间】:2017-03-12 22:20:15
【问题描述】:
我正在尝试完全理解 Angular2 final 的变更检测。
这包括:
- 处理变化检测策略
- 将变更检测器与组件连接和分离。
我以为我已经对这些概念有了相当清晰的了解,但为了确保我的假设正确,我写了一个小 plunkr 来测试它们。
我对全局正确的一般理解,但在某些情况下,我有点迷茫。
这里是 plunker:Angular2 Change detection playground
plunker 的快速解释:
很简单:
- 一个父组件,您可以在其中编辑一个属性,该属性将传递给两个子组件:
- 更改检测策略设置为 OnPush 的子项
- 更改检测策略设置为默认的子项
父属性可以通过以下任一方式传递给子组件:
- 更改整个属性对象,并创建一个新对象(“Change obj”按钮)(触发对 OnPush 子项的更改检测)
- 更改属性对象内的成员(“更改内容”按钮)(不会触发对 OnPush 子项的更改检测)
对于每个子组件,可以附加或分离 ChangeDetector。 (“detach()” 和 “reattach()” 按钮)
OnPush 子节点有一个额外的可以编辑的内部属性, 并且可以显式应用更改检测("detectChanges()" 按钮)
以下是我无法解释的行为:
场景1:
- 分离 OnPush 子项和默认子项的更改检测器(单击两个组件上的“detach()”)
- 编辑父属性名和姓
- 点击“Change obj”将修改后的属性传递给孩子
预期行为: 我希望 BOTH 个孩子不会被更新,因为他们的变化检测器都是分离的。
当前行为: 默认子级未更新,但 OnPush 子级已更新.. 为什么? 不应该,因为它的 CD 已分离...
场景 2:
- 为 OnPush 组件分离 CD
- 编辑其内部值输入并单击更改内部:没有任何反应,因为CD已分离,因此未检测到更改...确定
- 单击detectChanges():检测到更改并更新视图。到目前为止一切顺利。
- 再次编辑internal value输入并单击change internal:再次,没有任何反应,因为CD已分离,因此未检测到更改.. OK
- 编辑父属性 firstname 和 lastname。
- 点击“Change obj”将修改后的属性传递给孩子
预期行为: OnPush 子级根本不应该更新,再一次因为它的 CD 已分离...CD 根本不应该发生在这个组件上
当前行为: 值和内部值都被更新,像一张完整的 CD 一样的接缝被应用到这个组件上。
- 最后一次,编辑 internal value 输入并点击 change internal:检测到更改,并更新内部值...
预期行为: 不应更新内部值,因为 CD 仍处于分离状态
当前行为: 检测到内部值更改...为什么?
结论:
根据这些测试,我得出以下结论,这对我来说很奇怪:
- 采用 OnPush 策略的组件在其输入发生更改时'检测到更改',即使其更改检测器已分离。
- 具有 OnPush 策略的组件在每次输入更改时重新附加其更改检测器...
您如何看待这些结论?
你能用更好的方式解释这种行为吗?
这是一个错误还是预期的行为?
【问题讨论】:
-
不知道谁投了反对票。我认为这是一个非常有趣的问题,问题得到了完美的解释。
-
我不确定,但我想我看到它提到
detach()分离了儿童的变化检测器,而不是组件本身。我自己还没有深入研究变化检测。 -
文档说:“从变化检测器树中分离变化检测器。”使用默认 CD 策略附加/分离 CD 按预期与孩子一起工作
标签: angular plunker angular2-changedetection