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 个检测器。为什么??
哪位好心人能给我解释一下这是怎么回事?
谢谢!!
我觉得你对变化检测的理解是正确的。可能有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只考虑改变@Input。 ngOnChanges() 不会被触发,因为不会更改任何输入。
[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
我正在尝试了解 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 个检测器。为什么??
哪位好心人能给我解释一下这是怎么回事?
谢谢!!
我觉得你对变化检测的理解是正确的。可能有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只考虑改变@Input。 ngOnChanges() 不会被触发,因为不会更改任何输入。
[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