Was ist der Unterschied zwischen ngOnInit und ngAfterViewInit von Angular2?

78

Ich kann nicht verstehen, was der Unterschied zwischen ngOnInitund ist ngAfterViewInit.

Ich fand den einzigen Unterschied zwischen ihnen ist @ViewChild. Nach dem folgenden Code sind die elementRef.nativeElementin ihnen gleich.

Welche Szene sollen wir verwenden ngAfterViewInit?

@Component({
  selector: 'my-child-view',
  template: `
  <div id="my-child-view-id">{{hero}}</div>
  `
})
export class ChildViewComponent {
  @Input() hero: string = 'Jack';
}

//////////////////////
@Component({
  selector: 'after-view',
  template: `
    <div id="after-view-id">-- child view begins --</div>
      <my-child-view [hero]="heroName"></my-child-view>
    <div>-- child view ends --</div>`
    + `
    <p *ngIf="comment" class="comment">
      {{comment}}
    </p>
  `
})
export class AfterViewComponent implements AfterViewInit, OnInit {
  private prevHero = '';
  public heroName = 'Tom';
  public comment = '';

  // Query for a VIEW child of type `ChildViewComponent`
  @ViewChild(ChildViewComponent) viewChild: ChildViewComponent;

  constructor(private logger: LoggerService, private elementRef: ElementRef) {
  }

  ngOnInit() {
    console.log('OnInit');
    console.log(this.elementRef.nativeElement.querySelector('#my-child-view-id'));
    console.log(this.elementRef.nativeElement.querySelector('#after-view-id'));
    console.log(this.viewChild);
    console.log(this.elementRef.nativeElement.querySelector('p'));
  }

  ngAfterViewInit() {
    console.log('AfterViewInit');
    console.log(this.elementRef.nativeElement.querySelector('#my-child-view-id'));
    console.log(this.elementRef.nativeElement.querySelector('#after-view-id'));
    console.log(this.viewChild);
    console.log(this.elementRef.nativeElement.querySelector('p'));
  }
}
Zhiyuan Sonne
quelle

Antworten:

90

ngOnInit()wird aufgerufen, nachdem ngOnChanges()das erste Mal aufgerufen wurde. ngOnChanges()wird jedes Mal aufgerufen, wenn Eingaben durch Änderungserkennung aktualisiert werden.

ngAfterViewInit()wird aufgerufen, nachdem die Ansicht zum ersten Mal gerendert wurde. Deshalb @ViewChild()kommt es darauf an. Sie können nicht auf Ansichtsmitglieder zugreifen, bevor diese gerendert wurden.

Günter Zöchbauer
quelle
Wenn Sie " gerendert" sagen , meinen Sie damit, dass es auf dem Bildschirm angezeigt wird? (oder gesendet, um gerendert zu werden, um auf dem Bildschirm zu erscheinen)
Royi Namir
2
Wenn es dem DOM hinzugefügt wird. Wenn Sie festlegen, wird display: hiddenes bis zum Rendern angezeigt, ist jedoch auf dem Bildschirm nicht sichtbar. Wenn Sie das DOM jedoch mit den devtools des Browsers untersuchen, können Sie das Markup sehen.
Günter Zöchbauer
3
" Sie können nicht auf Ansichtsmitglieder zugreifen, bevor sie gerendert wurden " - Wie erklären Sie also, dass ViewChild(vc) auf verfügbar ist onNgInit? plnkr.co/edit/AzhRe6bjnuPLKJWEJGwp?p=preview , können Sie bitte erklären?
Royi Namir
5
@ Royi Ich kann Ihren Plunker nicht auf meinem Telefon öffnen und es wird einige Tage dauern, bis ich wieder an meinem Computer bin. Statisch hinzugefügte Elemente sind bereits in verfügbar ngOnInit. Wenn Sie Inhalte haben, die zum Beispiel von *ngForDatenübertragungen an eine übertragen werden @Input, sind diese Inhalte noch nicht verfügbar inngOnInit
Günter Zöchbauer
2
Vielen Dank für die Antwort. Das ist genau das Szenario. Also ich denke das ist es. i.imgur.com/Vbajl4F.jpg . Genieß deinen Urlaub.
Royi Namir
25

ngOnInit()wird direkt aufgerufen, nachdem die datengebundenen Eigenschaften der Direktive zum ersten Mal überprüft wurden und bevor eines ihrer untergeordneten Elemente überprüft wurde. Es wird nur einmal aufgerufen, wenn die Direktive instanziiert wird.

ngAfterViewInit()wird aufgerufen, nachdem die Ansicht einer Komponente und die Ansichten ihrer untergeordneten Elemente erstellt wurden. Es handelt sich um einen Lifecycle-Hook, der aufgerufen wird, nachdem die Ansicht einer Komponente vollständig initialisiert wurde.

JS dev
quelle
1

Inhalt ist das, was als Kinder weitergegeben wird. Ansicht ist die Vorlage der aktuellen Komponente.

Die Ansicht wird vor dem Inhalt initialisiert und ngAfterViewInit()daher vorher aufgerufen ngAfterContentInit().

** ngAfterViewInit()wird aufgerufen, wenn die Bindungen der untergeordneten Anweisungen (oder Komponenten) zum ersten Mal überprüft wurden. Daher ist es perfekt für den Zugriff auf und die Bearbeitung von DOM mit Angular 2-Komponenten. Wie @ Günter Zöchbauer bereits erwähnt hat, @ViewChild()läuft es also gut hinein.

Beispiel:

@Component({
    selector: 'widget-three',
    template: `<input #input1 type="text">`
})
export class WidgetThree{
    @ViewChild('input1') input1;

    constructor(private renderer:Renderer){}

    ngAfterViewInit(){
        this.renderer.invokeElementMethod(
            this.input1.nativeElement,
            'focus',
            []
        )
    }
}
STAHL
quelle
Ich denke du liegst hier falsch. ngAfterViewInit () wird erst ausgeführt, nachdem ngAfterContentChecked () und ngAfterContentChecked () erst nach ngAfterContentInit () und jedem nachfolgenden ngDoCheck () ausgeführt werden. Weitere Informationen finden Sie unter
Suneet Bansal