我试图理解Angular 2应用程序中的变化检测器机制。我想我在阅读几篇帖子方面取得了一些进展:)但不是很多。据我所知,情况是这样的:
当组件未使用OnPush策略时,它将在以下情况下运行相关的变更检测器:
1)应用程序的任何部分都会启动DOM事件 2)应用程序的任何部分解析HTTP请求 3)任何parte使用setTimeout或setInterval
执行异步代码将在组件树中从上到下检查所有组件。
当组件使用OnPush策略时,它将在以下情况下运行更改检测器:
1)任何@Input改变其引用(此处涉及Immutability) 2)组件(或子组件)发起事件 3)Observable发起一个事件。在这种情况下,如果我们将Observable用作@Input,那么我们必须在更改检测器中调用markForCheck()方法。
OnPush组件标记其所有组件子树,以便不运行更改检测。
更改检测始终从根组件开始,并将从组件树的顶部到底部。
所以我构建了一个示例应用程序(文本末尾的链接)和3个级别的组件树(父级,子级和大型子级)。第二级组件是OnPush组件。所有组件都附加了点击事件,因此当点击其中任何一个时,都会执行更改检测器。执行ngAfterViewChecked挂钩时,我将组件颜色更改为红色几秒钟。
我无法理解为什么当我点击所有儿童变化探测器正在运行的子孙组件时。我以为只有从父母到大子的子树中点击的那个才会被执行。
当我点击父母时是一样的。所有儿童探测器都被执行。为什么?
任何好人都可以向我解释发生了什么事?
谢谢!
答案 0 :(得分:4)
我觉得你对变化检测的理解非常重要。可能有2个误解,我想强调这可能有助于你解决这个难题。
1- ngAfterViewChecked 与是否检测到更改无关,文档[1]说"请注意,Angular经常调用AfterViewChecked,通常在没有感兴趣的更改时。编写精益挂钩方法以避免性能问题。"举个例子。
您可能希望使用 ngOnChanges() [2]。文档中说" Angular只在输入属性的值发生变化时才调用钩子"
2-当从组件中更改组件的状态(setTimeout,rx subscription fired,...)时,您需要注入 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