为什么在这种情况下 ngOnChanges 不是 运行? (Angular 文档示例)

Why ngOnChanges is not running in this case? (Angular Docs Example)

我正在学习 angular 并且我 运行 从 Angular 文档中学习这个 ngOnChanges 示例 (stackblitz) :

on-changes-parent.component.html

<h2>{{title}}</h2>
<label for="power-input">Power: </label>
<input type="text" id="power-input" [(ngModel)]="power">
<label for="hero-name"> Hero.name: </label>
<input type="text" id="hero-name" [(ngModel)]="hero.name">

<button type="button" (click)="reset()">Reset Log</button>

<on-changes [hero]="hero" [power]="power"></on-changes>

on-changes-parent.component.html

export class OnChangesParentComponent {
  hero!: Hero;
  power = '';
  title = 'OnChanges';
  @ViewChild(OnChangesComponent) childView!: OnChangesComponent;

  constructor() {
   this.reset();
  }

  reset() {
    // new Hero object every time; triggers onChanges
    this.hero = new Hero('Windstorm');
    // setting power only triggers onChanges if this value is different
    this.power = 'sing';
    if (this.childView) {
      this.childView.reset();
    }
  }
}

on-changes.component.ts

@Component({
  selector: 'on-changes',
  template: `
  <div class="info">
    <p>{{hero.name}} can {{power}}</p>

    <h3>Change Log</h3>
    <div *ngFor="let chg of changeLog" class="log">{{chg}}</div>
  </div>
  `
})
export class OnChangesComponent implements OnChanges {
  @Input() hero!: Hero;
  @Input() power = '';

  changeLog: string[] = [];

  ngOnChanges(changes: SimpleChanges) {
    for (const propName in changes) {
      console.log(propName)
      const chng = changes[propName];
      const cur  = JSON.stringify(chng.currentValue);
      const prev = JSON.stringify(chng.previousValue);
      this.changeLog.push(`${propName}: currentValue = ${cur}, previousValue = ${prev}`);
    }
  }

  reset() { this.changeLog = []; }
}

console.log 添加到 ngOnChanges 后,我注意到当我更新 Power 输入时它是 运行ning,但是,当我更新时它不是 运行ning更新 Hero.name。在这两种情况下,我都希望 ngOnChanges 为 运行。我错过了什么?非常感谢您的解释。

它不会触发,因为它仍然是您引用的同一个英雄,只是名称不同。由于 Angular 使用 === 检查更改,因此它决定对象没有更改。

解决这个问题的方法是在每次名称更改时创建一个新的英雄对象,或者实现 ngDoCheck 接口来实现您的自定义更改检测。