Жизненный цикл компонента


Каждый компонент имеет свой жизненный цикл (Component Lifecycle), в процессе которого вызываются ряд описывающих текущий этап методов (Angular Hooks):

OnChanges - устанавливаются или изменяются значения входных свойств класса компонента;
OnInit - устанавливаются "обычные" свойства; вызывается единожды вслед за первым вызовом OnChanges();
DoCheck - происходит изменения свойства или вызывается какое-либо событие;
AfterContentInit - в шаблон включается контент, заключенный между тегами компонента;
AfterContentChecked - аналогичен DoCheck(), только используется для контента, заключенного между тегами компонента;
AfterViewInit - инициализируются компоненты, которые входят в шаблон текущего компонента;
AfterViewChecked - аналогичен DoCheck(), только используется для дочерних компонентов;
OnDestroy - компонент "умирает", т. е. удаляется из DOM-дерева
В списке выше все методы перечислены в порядке их вызова.

Angular hooks реализованы в виде интерфейсов, реализующих функцию, совпадающую по названию с названием интерфейса + префикс ng.


export class ContactsItemComponent implements OnInit {
//
ngOnInit() {
console.log('OnInit')
}
//
}
Чтобы стало понятно, разберем пример.

hooks-example.component.ts


@Component({
selector: 'hooks-example',
template: `
<contacts-list [title]="'Managers'">
<contacts-item [name]="'Peter'"></contacts-item>
</contacts-list>
`,
})
export class HooksExampleComponent {}
contacts-list.component.ts


@Component({
selector: 'contacts-list',
template: `
<h2>Contacts List of {{ company }}</h2>
<ng-content></ng-content>
<contacts-item [name]="'Jack'"></contacts-item>
<contacts-item [name]="'Daniel'"></contacts-item>
`,
})
export class ContactsListComponent
implements
OnChanges,
OnInit,
DoCheck,
AfterContentInit,
AfterContentChecked,
AfterViewInit,
AfterViewChecked {
@Input() title: string

company: string = 'Google Inc.'

@ViewChild(ContactsItemComponent)
vwCh: ContactsItemComponent
@ContentChild(ContactsItemComponent)
cntCh: ContactsItemComponent

ngOnChanges(obj: SimpleChanges) {
console.log('OnChanges', obj)
}

ngOnInit() {
console.log('OnInit', this.company)
}

ngDoCheck() {
console.log('DoCheck')
}

ngAfterContentInit() {
console.log('AfterContentInit', this.cntCh)
}

ngAfterContentChecked() {
console.log('AfterContentChecked')
}

ngAfterViewInit() {
console.log('AfterViewInit', this.vwCh)
}

ngAfterViewChecked() {
console.log('AfterViewChecked')
}
}
contacts-item.component.ts


@Component({
selector: 'contacts-item',
template: ` <p>{{ name }}</p> `,
})
export class ContactsItemComponent {
@Input() name: string = null
}
Запустите приложение c открытой консолью браузера. На примере Component Lifecycle выглядит так:

Component Lifecycle

Первым вызывается OnChanges(), повторный вызов которого осуществляется при изменении хотя бы одного входного свойства. В качестве аргумента ему передается объект с текущим и предыдущим значениями измененных @Input() свойств.

Если входные свойства отсутствуют, то метод не будет вызван.

Следом вызывается OnInit(), который говорит о том, что инициализированы внутренние свойства компонента, в данном случае свойство company. Метод вызывается только один раз.

Третьим по счету идет DoCheck(), который отслеживает изменения, не связанные со свойствами. Его вызов осуществляется довольно часто, в ответ на каждое взаимодействие пользователя с интерфейсом (например, фокусировка поля формы или потеря фокуса).

Далее инициализируются шаблоны. Сначала подгружается контент, находящийся между тегами компонента. За это отвечает ngAfterContentInit().

Для отображения переданного контента в представлении компонента используется парный тег <ng-content></ng-content>.

На этом этапе Component Lifecycle можно получить переданный извне компонент. Для этого используется декоратор @ContentChild(), который в качестве аргумента принимает название компонента, также рекомендуется указывать его тип. Передавать можно не только компонент, но и обычный HTML, доступ к которому осуществляется через ссылку на него, подробно здесь.


@ContentChild(ContactsItemComponent) contentChild: ContactsItemComponent;
Следующим при любых изменениях во внешнем шаблоне вызывается ngAfterContentChecked().

Если вам нужно получить все экземпляры указанного компонента, используйте декоратор @ContentChildren().

Методы ngAfterViewInit() и ngAfterViewChecked() схожи с ngAfterContentInit() и ngAfterContentChecked() лишь с тем различием, что первые два вызываются после полной иницализации шаблона.

Используя декораторы @ViewChild() и @ViewChildren() можно получить доступ к прямым дочерним компонентам.

Как и сами Angular Hooks, декораторы находятся в библиотеке @angular/core.

Чтобы инициировать вызов OnDestroy(), необходимо удалить компонент из DOM-дерева (переход на другой URL или с помощью *ngIf).