Почему хук ngOnChanges не вызывается?

avatar
SamuraiJack
8 апреля 2018 в 08:48
317
1
2

Я пытаюсь изучить Angular 2 путем экспериментов и обнаружил, что ngOnChanges не срабатывает в следующем коде:

app.component.ts:

import { Component, Input } from "@angular/core"
import { FormsModule } from '@angular/forms';
import { OnChanges, SimpleChanges } from '@angular/core/src/metadata/lifecycle_hooks';
@Component({
  selector: 'my-app',
  template: `
    Enter text : <input type="text" [(ngModel)]='userText'  />
    <br/>
    Entered text :  {{userText}} 
  `
})

export class AppComponent {
  @Input()  userText: string;
  name: string = "Tom";

  ngOnChanges(changes: SimpleChanges): void {
    for (let propertyName in changes) {
      let change = changes[propertyName];
      let current = JSON.stringify(change.currentValue);
      let previouis = JSON.stringify(change.previousValue);
      console.log(propertyName + ' ' + current + ' ' + previouis);
    }

  }
}

Приведенный выше код не срабатывает ngOnChanges

Однако, если я создам отдельный "простой" компонент и использую его в app.scomponent.ts, будет работать следующее:

app.component.ts:

import {Component} from "@angular/core"
import {FormsModule} from '@angular/forms'; 
@Component({
  selector: 'my-app',
  template: `
    Enter text : <input type="text" [(ngModel)]='userText' />
    <br/>
    <simple [simpleInput]='userText'></simple>
  `
})

export class AppComponent{
  userText:string;
  name:string ="Tom";


}

simple.component.ts:

import {Component,Input} from '@angular/core';
import { OnChanges,SimpleChanges } from '@angular/core/src/metadata/lifecycle_hooks';

@Component({
    selector:'simple',
    template: `You entered {{simpleInput}} `
})
export class SimpleComponent implements OnChanges{
    ngOnChanges(changes: SimpleChanges): void {
        for(let propertyName in changes){
            let change=changes[propertyName];
            let current=JSON.stringify(change.currentValue);
            let previouis=JSON.stringify(change.previousValue);
            console.log(propertyName+ ' '+current+ ' ' +previouis);
        }

    }
    @Input() simpleInput: string;

}

Кто-нибудь может объяснить? Что я здесь делаю не так?

Источник
Jota.Toledo
8 апреля 2018 в 08:51
0

angular.io/guide/lifecycle-hooks#onchanges Angular calls its ngOnChanges() method whenever it detects changes to input properties

SamuraiJack
8 апреля 2018 в 08:57
0

@Jota.Toledo, если Angular вызывает свой метод ngOnChanges() всякий раз, когда обнаруживает изменения во входных свойствах, то почему он не вызывает его, когда userText является входным свойством и изменяется?

Jota.Toledo
8 апреля 2018 в 09:01
0

Потому что изменение должно быть отправлено контейнером компонента. Во втором сценарии у вас есть appcomponent, передающий данные в simplecomponent через свойство ввода. В первом сценарии это не так, поскольку appcomponent является вашим корневым компонентом, а это означает, что он не является контейнером для другого.

user184994
8 апреля 2018 в 09:02
0

Вы не можете предоставлять входные данные загрузочному компоненту, такому как AppComponent. Дополнительная информация на coderhelper.com/questions/42412603/…

Jota.Toledo
8 апреля 2018 в 09:04
0

Можно, но бессмысленно.

SamuraiJack
8 апреля 2018 в 09:43
0

@Jota.Toledo означает, что если я хочу регистрировать предыдущие и текущие значения текстового поля. Я ДОЛЖЕН создать отдельный компонент, такой как simple component в этом случае, а затем передать значения из app.component в простой компонент? Разве это не непродуктивно?

Jota.Toledo
8 апреля 2018 в 09:48
1

Вам не необходимо, это вариант да, но есть и другие: rxjs+неизменяемость или используйте событие (ngModelChange) для регистрации изменения. Если вы хотите использовать API SimpleChanges для ведения журнала, вы действительно обязаны использовать входные свойства.

Ответы (1)

avatar
Jörg Reichardt
8 апреля 2018 в 11:13
0

Я думаю, вы можете неправильно понять назначение полей @Input. Поля @Input позволяют обмениваться данными между родительским и дочерним компонентами, они не нужны для привязки данных внутри компонента. Для привязки данных не требуется никаких атрибутов, поля просто должны быть общедоступными. В качестве хука жизненного цикла ngOnChanges предназначен для реагирования на изменения в полях @Input, а не на элементах ввода html.

Если вам нужно более сложное поведение при изменении, чем двусторонняя привязка данных, попробуйте

<input type="text" [(ngModel)]='userText' (ngModelChange)="onUserTextChange($event)">

(Извините, если вышеприведенный код не работает "из коробки", я протестирую и исправлю его, как только вернусь к своей машине разработчика)

Дополнительную информацию можно найти здесь.