使用 getter 和 setter 拦截 @Input 变化

Intercepting @Input changes with getter and setter

我尝试使用 @Input 属性 的 Typescript 访问器来拦截从 parent 到 child 的更改。我对 docs 中的这个例子做了一点改动。

我在 parent 的方法中设置了两个 parent 属性更改,期望 child 的绑定 Input 属性将随之而来。我发现当 parent 中的 属性 如下更改时,setter 仅触发一次:

  this.name="John"; //but this.name = this.name + "r" will work

虽然对于这个它总是有效:

  this.age++; // or  this.age = this.age + 1;

为了修复第一个问题,我需要 'notify' parent 在输出中使用 EventEmitter(我已经尝试过,并且有效),但为什么第二个不需要它?有人可以解释两者之间的真正区别以及为什么它不适用于第一个(或者为什么它适用于第二个)。

DEMO


Parent class: ...

  name = 'Jane';
  age = 10;

  changeName(){
    this.name= "John";
  }

  changeAge(){
    this.age++;
  }

Parent 视图:

<my-name [name]="name"></my-name>
<button (click)="changeName()">Click me to change the name</button>

<my-age [age]="age"></my-age>
<button (click)="changeAge()">Click me to change the age</button>

孩子 1 Class:

 private _name = '';

  @Input()
  set name(name: string) {
    this._name = (name && name.trim()) || '<no name set>';
    console.log(name);
  }

  get name(): string { return this._name; }

子 1 视图:

  My name is {{name}}.

孩子 2 class: 私人年龄 = 0;

 @Input()
  set age(age: number) {
    this._age = age || 0;
    console.log(age);
  }

  get age(): number { return this._age; }

儿童 2 视图

  I am {{age}} years old

经过一些研究和反思,我 found/remembered 只有在检测到变化时才会更新绑定。 所以如果 name 属性 设置如下:

this.name= "John";

第一个 运行 更改了 属性 的初始值,因此访问器被触发。对于第二次和其他时间,相同的语句不会触发更改检测,因为值没有更改(它已经是 "John"),因此访问器不会触发。
而对于 age 属性,它总是随着递增而变化:

this.age++;

所以更改检测和访问器总是被触发。