Angular 2 变化检测器

Angular 2 change detector

我正在尝试了解 Angular 2 个应用程序中的变化检测器机制。我想我在阅读几篇文章时取得了一些进步 :) 但不是很多。据我了解情况是这样的:

当组件未使用 OnPush 策略时,它将 运行 关联的更改检测器,以防:

1) 应用程序的任何部分都会启动一个 DOM 事件 2) 应用程序的任何部分解析 HTTP 请求 3) 任何部分使用 setTimeout 或 setInterval

执行异步代码

将在组件树中从上到下检查所有组件。

当组件使用 OnPush 策略时,它将 运行 更改检测器在以下情况下:

1) 它的任何@Input 都改变了它的引用(这里涉及不可变性) 2)组件(或child)发起一个事件 3) Observable 发起一个事件。在这种情况下,如果我们使用 Observable 作为 @Input 那么我们必须在变化检测器中调用 markForCheck() 方法。

OnPush 组件将其所有组件子树标记为不 运行ning 更改检测。

变更检测总是从根组件开始,然后从上到下遍历组件树。

所以我构建了一个示例应用程序(链接在文末),其中包含 3 个级别的组件树(parent、child 和 grand-child)。二级组件是 OnPush 组件。所有组件都附加了单击事件,因此当单击其中任何一个时,都会执行更改检测器。当执行 ngAfterViewChecked 钩子时,我将组件颜色更改为红色几秒钟。

我无法理解的是,为什么当我单击 grand-child 组件时,所有 child 变化检测器都是 运行ning。我还以为只有在 parent 到 grand-child 的子树中点击的才会被执行。

当我点击parent时也是一样。执行所有 childs 个检测器。为什么??

哪位好心人能给我解释一下这是怎么回事?

谢谢!!

Github project

Github pages deployed project

我觉得你对变化检测的理解是正确的。可能有2个误解我想强调一下,可能会帮助你解决这个难题。

1- ngAfterViewChecked 与是否检测到更改无关,文档[1] 在示例后说 "Notice that Angular frequently calls AfterViewChecked, often when there are no changes of interest. Write lean hook methods to avoid performance problems."。

您可能想改用 ngOnChanges()[2]。文档说 "Angular only calls the hook when the value of the input property changes"

2- 当从组件内部更改组件的状态时(setTimeout、触发 rx 订阅...),您需要注入 ChangeDetectorRef 并调用 ChangeDetectorRef.markForCheck()[3].

这是因为OnPush只考虑改变@InputngOnChanges() 不会被触发,因为不会更改任何输入。

[1] https://angular.io/docs/ts/latest/guide/lifecycle-hooks.html#!#aftercontent

[2] https://angular.io/docs/ts/latest/guide/lifecycle-hooks.html#!#onchanges

[3] https://angular.io/docs/ts/latest/api/core/index/ChangeDetectorRef-class.html