为什么在推送更改检测时属性更改仍然导致 @Input 在 ngDoCheck 中发生更改?

Why does attribute change still cause the @Input to be change in ngDoCheck when change detection is on push?

考虑这个plunker

@Component({
  changeDetection: ChangeDetectionStrategy.OnPush,
  selector: 'my-app-n1',
  template: `
    <my-app-n2 [from2]="from1"></my-app-n2>
    <div>
      {{from1.name}}
      <input type="button" value="n1"  (click)="changen1()">
    </div>
  `,
})
export class App2 {

  @Input() from1;

  ngDoCheck() {
    console.log('do check 1 ', this.from1);
  }

  ngOnChanges(changes: any) {
    console.log('n1 change ', changes);
  }  
  changen1() {
    this.from1 = {'name': 'name1-2'}
  }
}

@Component({
  selector: 'my-app',
  template: `
    <my-app-n1 [from1]="from"></my-app-n1>
    <input type="button" value="root" (click)="changen0()">
  `,
})
export class App {
  from: any;
  constructor() {
    this.from = {'name': 'name0'}
  }

  ngOnChanges(changes: any) {
    console.log('n0 change ', changes);
  }  

  changen0() {
    this.from.name = 'name-0-2-2'
  }

}

注意 App2 使用 ChangeDetectionStrategy.OnPush

单击 changen0 时,我希望 ngOnChanges 不会被调用(因为没有分配新的引用)并且 ngDoCheck 会被调用 this.from1 以具有数据 {'name': 'name0'} 并且视图仍然显示 name0

而是

ngDoCheck 被调用 this.from1 等于 {'name': 'name-0-2-2'}

并且视图正在显示 name0

我的问题如下

  1. 为什么 属性 this.from1 变了?

  2. 而且如果换了模型为什么视图和模型不一致?

您正在为 App2 使用 ChangeDetectionStrategy.OnPush,这意味着除非更新输入绑定 [from1]="from",否则不会为 App2 触发 CD。

因此,当您在此处更新 name 属性 时,name 会更新:

changen0() {
    this.from.name = 'name-0-2-2'
}

您没有更新对 this.from 的引用,因此不会触发 App2 的更改检测,因此您看不到 HTML 中的更改。 ngOnChanges 也没有被调用。

ngDoCheck is called with this.from1 equal {'name': 'name-0-2-2'}

ngDoCheck 并不意味着您的组件正在被检查。它在 Angular 检查父组件时调用。阅读这篇文章了解更多信息: