Яка різниця між ngOnInit та ngAfterViewInit для Angular2?


80

Я не можу зрозуміти, в чому різниця ngOnInit і ngAfterViewInit.

Я знайшов єдину різницю між ними @ViewChild . Відповідно до наступного коду, elementRef.nativeElementв них однакові.

Яку сцену нам використовувати 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'));
  }
}

Відповіді:


95

ngOnInit()називається після того, як ngOnChanges()був викликаний вперше. ngOnChanges()викликається кожного разу, коли вхідні дані оновлюються шляхом виявлення змін.

ngAfterViewInit()викликається після подання подання. Ось чому це @ViewChild()залежить від цього. Ви не можете отримати доступ до членів перегляду до їх відображення.


Коли ви говорите " відтворено" , ви маєте на увазі, що воно відображається на екрані? (або надіслано для надання для відображення на екрані)
Рої Намір

2
Коли він додається до DOM. Якщо ви встановите display: hiddenйого до відображення, але не відображатиметься на екрані. Але якщо ви дослідите DOM за допомогою devtools браузера, ви зможете побачити розмітку.
Günter Zöchbauer

3
" ви не можете отримати доступ до членів представлення до їх відображення " - То як ви пояснюєте, що ViewChild(vc) доступний на onNgInit? plnkr.co/edit/AzhRe6bjnuPLKJWEJGwp?p=preview , Ви можете пояснити?
Ройі Намір,

6
@Royi Я не можу відкрити ваш Plunker на своєму телефоні, і це пройде кілька днів, поки я повернусь до свого комп’ютера. Статично додані елементи вже доступні в ngOnInit. Якщо у вас є вміст, який надається для перевірки шляхом *ngForпередачі даних до @Input, цей вміст ще не буде доступний уngOnInit
Гюнтер Цохбауер,

2
Щиро дякую за відповідь. Саме такий сценарій. Тож я здогадуюсь, це все. i.imgur.com/Vbajl4F.jpg . Насолоджуйся відпусткою.
Рої Намір,

27

ngOnInit()викликається відразу після того, як властивості, пов'язані з даними директиви, були перевірені вперше, і перед тим, як перевірено будь-яке з її дочірніх елементів. Він викликається лише один раз, коли директива є інстанційованою.

ngAfterViewInit()називається після перегляду компонента та створення поглядів його дітей. Це гачок життєвого циклу, який викликається після повного ініціалізації подання компонента.


1

Зміст - це те, що передається в дитинстві. Перегляд - це шаблон поточного компонента.

Представлення ініціалізується перед вмістом і ngAfterViewInit()тому викликається раніше ngAfterContentInit().

** ngAfterViewInit()викликається, коли прив'язки дочірніх директив (або компонентів) були перевірені вперше. Отже, він ідеально підходить для доступу до DOM і керування ним за допомогою компонентів Angular 2. Як @ Günter Zöchbauer було згадано раніше, це правильно, @ViewChild()отже, все працює в ньому.

Приклад:

@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',
            []
        )
    }
}

Я думаю, ви тут помиляєтесь. ngAfterViewInit () виконується лише після того, як ngAfterContentChecked (), а ngAfterContentChecked () виконується лише після ngAfterContentInit () та кожного наступного ngDoCheck (). Будь ласка, зверніться до деталей кутових гачків життєвого циклу, щоб отримати докладнішу інформацію angular.io/guide/lifecycle-hooks
Suneet Bansal
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.