[ Angular 2 : Lifecycle Hook ] 라이프 사이클

실행순서

  1. ngOnChanges
  2. ngOnInit
  3. ngDoCheck
  4. ngAfterContentInit
  5. ngAfterContentChecked
  6. ngAfterViewInit
  7. ngAfterViewChecked

각 라이프 사이클 설명

1. ngOnChanges

Data-bound Property 값이 변할 때.

2. ngOnInit

ngOnChanges가 처음 실행되고 나서, 컴포넌트가 시작될 때. ( ngOnChanges 가 Data-bound Property 값이 변경될 때마다 실행되는 반면, ngOnInit는 첫번째 ngOnChanges 실행 이후 단 한번만 실행된다. )

3. ngDoCheck

Angular 2 Change Detection Cycle 이 가동 될 때마다 실행된다. ngOnChanges 는 Data-bound Property 값이 변경될 때만 실행되지만, ngDoCheck은 Angular2의 ‘Detection Cycle’ 마다 실행되게 된다. 즉, Property에 변경 내용이 없더라도 실행이 되게 된다.

4. ngAfterContentInit

Content( <ng-content> )가 삽입된 이후에 실행됨. 만약 ng-content 를 사용하지 않았다면, 신경쓸 필요가 없는 Hook 이다.

5. ngAfterContentChecked

ng-content 안의 내용에 대한 Change detection 이 실행된 후. ngAfterContentInit와 마찬가지로 ng-content를 사용하지 않았다면, 해당 사항 없다.

6. ngAfterViewInit

컴포넌트에 속한 모든 View 와 Child View 가 시작되고 나서. 즉, html 내용이 모두 표시되고 나서 실행된다.

7. ngAfterViewChecked

컴포넌트의 View와 Child View에 대한 변경사항이 체크되고 나서 실행된다.

Life Cycle Test Example

app.component.ts

import { Component } from '@angular/core';

@Component({
  selector: 'app-root',
  template: `
    <h1>Life Cycle Component</h1>
    <app-lifecycle *ngIf="!delete"></app-lifecycle>
    <button (click)="delete=true">Click to Delete</button>
  `,
  styles: [``]
})
export class AppComponent {
  delete = false;
}

 

lifecycle.component.ts

import { Component } from '@angular/core';
import { 
  OnChanges,
  OnInit,    
  DoCheck, 
  AfterContentInit, 
  AfterContentChecked,
  AfterViewInit,
  AfterViewChecked,
  OnDestroy
} from '@angular/core';

@Component({
  selector: 'app-lifecycle',
  template: `
    <p>
      lifecycle Works!
    </p>
  `,
  styles: []
})
export class LifecycleComponent implements 
  OnChanges,
  OnInit,    
  DoCheck, 
  AfterContentInit, 
  AfterContentChecked,
  AfterViewInit,
  AfterViewChecked,
  OnDestroy {

  constructor() { }

  ngOnChanges() {
    this.log('ngOnChanges');
  }
  ngOnInit() {
    this.log('ngOnInit');
  }
  ngDoCheck() {
    this.log('ngDoCheck');
  }
  ngAfterContentInit() {
    this.log('ngAfterContentInit');
  } 
  ngAfterContentChecked() {
    this.log('ngAfterContentChecked');
  }
  ngAfterViewInit() {
    this.log('ngAfterViewInit');
  }
  ngAfterViewChecked() {
    this.log('ngAfterViewChecked');
  }
  ngOnDestroy() {
    this.log('ngOnDestroy');
  }

  private log(hook:string){
    console.log(hook);
  }

}

브라우저에서 실행하면 다음과 같이 콘솔창에 각 단계가 표시된다. 버튼을 누르면, lifecycle Work! 라는 내용이 사라지면서 ngDestroy 가 콘솔창에 표시될 것이다.

Life Cycle Test Example 2

보다 상세하게 어떻게 라이프 사이클이 작동하는 지 알아보자.

app.component.ts

import { Component } from '@angular/core';

@Component({
  selector: 'app-root',
  template: `
    <h1>Life Cycle Component</h1>
    <app-lifecycle *ngIf="!delete" [bindable]="boundValue">
      <p #boundContent>{{test}}</p>
    </app-lifecycle>
    <button (click)="delete=true">Click to Delete</button>
    <button (click)="test='Changed value'">Click to Change Content</button>
    <button (click)="boundValue=2000">Click to Change Value</button>
  `,
  styles: [``]
})
export class AppComponent {
  delete = false;
  test = 'Starting Value';
  boundValue = 1000;
}

 

lifecycle.component.ts

import { Component, Input, ViewChild, ContentChild, ElementRef } from '@angular/core';
import {
  OnChanges,
  OnInit,
  DoCheck,
  AfterContentInit,
  AfterContentChecked,
  AfterViewInit,
  AfterViewChecked,
  OnDestroy
} from '@angular/core';

@Component({
  selector: 'app-lifecycle',
  template: `
    <ng-content></ng-content>
    <hr>
    <p #boundParagraph>bindable Property: {{bindable}}</p>    
    <p>{{boundParagraph.textContent}}</p>
  `,
  styles: []
})
export class LifecycleComponent implements
  OnChanges,
  OnInit,
  DoCheck,
  AfterContentInit,
  AfterContentChecked,
  AfterViewInit,
  AfterViewChecked,
  OnDestroy {

  @Input() bindable = 1000;

  @ViewChild('boundParagraph') 
  boundParagraph: ElementRef;

  @ContentChild('boundContent')
  boundContent: ElementRef;

  constructor() { }

  ngOnChanges() {
    this.log('ngOnChanges');
  }
  ngOnInit() {
    this.log('ngOnInit');
  }
  ngDoCheck() {
    this.log('ngDoCheck');
  }
  ngAfterContentInit() {
    this.log('ngAfterContentInit');
    console.log(this.boundContent);
  }
  ngAfterContentChecked() {
    this.log('ngAfterContentChecked');
  }
  ngAfterViewInit() {
    this.log('ngAfterViewInit');
    console.log(this.boundParagraph);
  }
  ngAfterViewChecked() {
    this.log('ngAfterViewChecked');
  }
  ngOnDestroy() {
    this.log('ngOnDestroy');
  }

  private log(hook: string) {
    console.log(hook);
  }

}

 

Content vs View

Content와 View를 분명히 구분할 줄 알아야 라이프 사이클을 이해할 수 있다. content 는 ng-content 처럼 바깥에서 컴포넌트 안으로 가져온 것. view는 원래 해당 컴포넌트 안에 존재하는 것.

html 안에 정의한 view child 나 content child 는 직접적으로 logic (ts files) 에서 참조해 가져올 수 없다. 따라서, @ViewChild() 나 @ContentChild() 와 같은 데코레이터를 이용해 가져온다. Dom Element 에 접근하는 법이다.

각 버튼을 실행시켜보면서 동작 상황을 살펴보자.

 

댓글 남기기