All components and directives in Angular have the same lifecycle hooks, defined in the @angular/core library; Probably many beginners (including me -). -) knows only ngOnInit() and ngOnDestroy(). Here’s a quick look at the order and function of several Angular life cycles.

Execution order

Angular lifecycle hooks have the following, in order of invocation:

ngOnChanges() -> ngOnInit() -> ngDoCheck() -> ngAfterContentInit() -> ngAfterContentChecked() -> ngAfterViewInit() -> ngAfterViewChecked() -> ngOnDestroy()

role

ngOnChanges()

The first call to this hook must be made before ngOnInit() is executed. It is usually used to detect changes in the Input property of a component/directive. Once the Input property of this component (@input) changes, NGX starts the ngOnChanges() method for that component.

Usage:

    ngOnChanges(changes: SimpleChanges) {
        console.log(changes);
        // Changes.prop.firstchange === true when ngOnchanges() is called for the first time;
        / / and changes. Prop. PreviousValue = = = is undefined
    }
Copy the code

Note:

NgOnChanges () can only detect changes to the input property, but not to the internal property. This means that unlike $watch() in angular.js, the hook can detect changes to the internal property and execute the corresponding callback function. NgOnChanges () does not;

Even for input properties, ngOnChanges() fires when input properties change if they are immutable types such as strings, numbers, etc.

NgOnChanges () is not triggered if the input property is a reference to an array, object, or push into an array. Angular only cares if the reference to the property changes, not if an object property changes.

If you want to trigger ngOnChanges() on array push, you should rewrite push as this.array = […this.array, item].

Obj = object. assign({}, this.obj, {name: ‘blabla’}) or this.obj = {… this.obj, name: ‘blabla’}

Here is a simple example using es7 expanders, but also immutable data types such as immutable.

ngOnInit()

Angular initializes a directive/component after displaying the data binding for the first time and setting the input properties for the component/directive. If you create components with ng g component, component files created by @angular/ CLI come with ngOnInit().

That is, ngOnInit() is executed only once after the constructor of the component/instruction class is executed. Normally, we put some initialization logic in ngOnInit(), such as fetching data from the initial interface. Angular has finished binding the input property at this point because the constructor has been executed. So you can safely send Ajax requests using these attributes as parameters.

ngOnDestroy()

Angular calls this method every time a component/directive is destroyed. In ngOnDestroy(), we unsubscribe observable objects, unsubscribe timers, etc., to prevent memory leaks.

For unsubscribe, not all observables require you to manually unsubscribe, see https://medium.com/@benlesh/rxjs-dont-unsubscribe-6753ed4fda87

ngDoCheck()

We used object. assign and ES7 expanders to solve the problem that ngOnChanges() cannot detect the push of an array or the direct modification of an Object’s property value. Angular itself provides the ngDoCheck() lifecycle hook to detect changes that it cannot detect.

This hook is similar to the $watch() method in angular.js, which triggers the lifecycle hook whenever the component’s property changes. Therefore, it will trigger very frequently, so do not write complicated logic in it, which will cause the program to be extremely expensive.

NgAfterContentInit () and ngAfterContentChecked ()

Both afterContent hooks are triggered when Angular casts a content projection.

NgAfterContentInit () is executed after ngDoCheck() is executed for the first time and only once.

A content projection is a way to insert the HTML content of another component into the location specified by this component. You’ll usually have a
element in the placeholder.

Content projections exist when there are other HTML tags in a component’s tag.

NgAfterContentChecked () is executed after each change detection of the projected component is completed, the first time after the first call to ngAfterContentInit().

The two hooks in the component view to accomplish before, so at this point is still can update properties without fear of triggering ExpressionChangedAfterItHasBeenCheckedError components.

NgAfterViewInit () and ngAfterViewChecked ()

Angular calls a component’s child views every time they are created (that is, views of the child components within the component).

To access a child view, you need to do so via the @viewChild () decorator property.

// app.component.ts
import { Component, AfterViewInit, AfterViewChecked, ViewChild } from '@angular/core';
import { DetailComponent } from './detail/detail.component';

@Component({
  selector: 'app-root',
  templateUrl: ` 
      
`
, styleUrls: [] }) export class AppComponent implements AfterViewInit, AfterViewChecked { @ViewChild(DetailComponent) detailView: DetailComponent; ngAfterViewInit() { console.log('after view init'); } ngAfterViewChecked() { console.log('after view checked, '.this.detailView); }}Copy the code
// detail.component.ts
import { Component, OnInit } from '@angular/core';

@Component({
  selector: 'app-detail',
  templateUrl: `<input type="text" [(ngModel)]="innerName">`,
  styleUrls: []
})
export class DetailComponent implements OnInit {

  public innerName = 'yyz';

  constructor() { }

  ngOnInit() {}
}
Copy the code

In the example above, ngAfterViewChecked() in the parent component fires every time you change the value of the input box in the child component and can retrieve the property values in the child component. NgAfterViewChecked () is also a frequently called lifecycle, so the code logic should be minimal;

In addition, if the ngAfterViewChecked () directly modifying component properties, will trigger a mistake ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked. The specific reasons for this error can be written in another article, which is not repeated here. Angular’s own single-dataflow rules prohibit updating a view after it has been assembled. Both afterView hooks are fired after the view has been composed. To avoid this error, push the action to the next event loop in the browser.

ngAfterViewChecked() {
    console.log('after view checked, '.this.detailView);
    // this will throw one error
    // this.title = this.detailView.innerName + 'after';
    if (this.detailName ! = =this.detailView.innerName + 'after') {
      setTimeout((a)= > {
        this.detailName = this.detailView.innerName + 'after'; }); }}Copy the code

The end! ha