可以说我有一个像这样的组件结构:

AppComponent
    HeaderComponent
    ContentComponent
        TodosComponent
            TodoComponent

如果我将HeaderComponent的changeDetection设置为ChangeDetectionStrategy.OnPush并在TodoComponent中进行更改,则仍会触发HeaderComponent的ngDoCheck()ngAfterViewChecked()ngAfterContentChecked()

我想念什么? ngDoCheck是否会被触发?如果是,如何确定ChangeDetection是否检查了组件?

最佳答案

是的,这是正确的行为。文章If you think ngDoCheck means your component is being checked — read this article详细解释了该行为。这是简短的版本。

在检查组件之前,会触发ngDoCheck。这样做是为了允许您执行一些自定义逻辑,然后标记组件以进行检查。您知道Angular通过对象引用跟踪@Input,但是您可以使用ngDoCheck进行自定义跟踪。这是简单的示例:

Component({
   ...,
   changeDetection: ChangeDetectionStrategy.OnPush
})
MyComponent {
   @Input() items;
   prevLength;
   constructor(cd: ChangeDetectorRef) {}

   ngOnInit() {
      this.prevLength = this.items.length;
   }

   ngDoCheck() {
      if (this.items.length !== this.prevLength) {
         this.cd.markForCheck();
      }
   }

请记住,ngDoCheck仅针对使用策略OnPush的顶级组件触发。这不是针对此子组件触发的。

同样正确的是,即使现在已完成检查,也会为该组件触发ngAfterViewChecked。这也是设计使然。

我强烈建议您阅读Everything you need to know about change detection in Angular,特别是Exploring the implications部分。它显示了您要查找的操作顺序。

另请阅读Why do we need ngDoCheck

10-06 00:10