constructor和ngOnInit鉤子有什麼不一樣?app
constructor(構造函數)是ES6類或TypeScript類中的特殊方法,而不是Angular的方法,主要用來作初始化操做,在進行類實例化操做是,會被自動調用。經過constructor方法並不能使咱們知道Angular什麼時候完成了組件的初始化工做。函數
僅顯示constructor方法:this
import { Component } from '@angular/core'; @Component({}) class ExampleComponent { // this is called by the JavaScript engine // rather than Angular constructor(name) { console.log('Constructor initialised'); this.name = name; } } // internally calls the constructor let appCmp = new ExampleComponent('AppCmp'); console.log(appCmp.name);
運行以上代碼,控制檯輸出結果:spa
Constructor initialization
AppCmp
constructor方法是由JavaScript引擎調用的,而不是Angular,這就是爲何ngOnInit生命週期鉤子被建立的緣由。code
ngOnInit 是 Angular 2 組件生命週期中的一個鉤子,Angular 2 中的全部鉤子和調用順序以下:component
ngOnChanges - 當數據綁定輸入屬性的值發生變化時調用對象
ngOnInit - 在第一次 ngOnChanges 後調用blog
ngDoCheck - 自定義的方法,用於檢測和處理值的改變生命週期
ngAfterContentInit - 在組件內容初始化以後調用ip
ngAfterContentChecked - 組件每次檢查內容時調用
ngAfterViewInit - 組件相應的視圖初始化以後調用
ngAfterViewChecked - 組件每次檢查視圖時調用
ngOnDestroy - 指令銷燬前調用
其中 ngOnInit 用於在 Angular 獲取輸入屬性後初始化組件,該鉤子方法會在第一次 ngOnChanges 以後被調用。
另外須要注意的是 ngOnInit 鉤子只會被調用一次,咱們來看一下具體示例:
import { Component, OnInit } from '@angular/core'; @Component({ selector: 'my-app', template: ` <h1>Welcome to Angular World</h1> <p>Hello {{name}}</p> `, }) export class AppComponent implements OnInit { name: string = ''; constructor() { console.log('Constructor initialization'); this.name = 'Semlinker'; } ngOnInit() { console.log('ngOnInit hook has been called'); } }
以上代碼運行後,控制檯輸出結果:
Constructor initialization
ngOnInit hook has been called
接下來看一個父-子組件傳參的例子:
parent.component.ts
import { Component } from '@angular/core'; @Component({ selector: 'exe-parent', template: ` <h1>Welcome to Angular World</h1> <p>Hello {{name}}</p> <exe-child [pname]="name"></exe-child> `, }) export class ParentComponent { name: string = ''; constructor() { this.name = 'Semlinker'; } }
child.component.ts
import { Component, Input, OnInit } from '@angular/core'; @Component({ selector: 'exe-child', template: ` <p>父組件的名稱:{{pname}} </p> ` }) export class ChildComponent implements OnInit { @Input() pname: string; // 父組件的名稱 constructor() { console.log('ChildComponent constructor', this.pname); // Output:undefined } ngOnInit() { console.log('ChildComponent ngOnInit', this.pname); } }
以上代碼運行後,控制檯輸出結果:
ChildComponent constructor undefined
ChildComponent ngOnInit Semlinker
咱們發如今 ChildComponent 構造函數中,是沒法獲取輸入屬性的值,而在 ngOnInit 方法中,咱們能正常獲取輸入屬性的值。由於 ChildComponent 組件的構造函數會優先執行,當 ChildComponent 組件輸入屬性變化時會自動觸發 ngOnChanges 鉤子,而後在調用 ngOnInit 鉤子方法,因此在 ngOnInit 方法內能獲取到輸入的屬性。
在 Angular 2 中,構造函數通常用於依賴注入或執行一些簡單的初始化操做。
import { Component, ElementRef } from '@angular/core'; @Component({ selector: 'my-app', template: ` <h1>Welcome to Angular World</h1> <p>Hello {{name}}</p> `, }) export class AppComponent { name: string = ''; constructor(public elementRef: ElementRef) { // 使用構造注入的方式注入依賴對象 this.name = 'Semlinker'; // 執行初始化操做 } }
在項目開發中咱們要儘可能保持構造函數簡單明瞭,讓它只執行簡單的數據初始化操做,所以咱們會把其餘的初始化操做放在 ngOnInit 鉤子中去執行。如在組件獲取輸入屬性以後,需執行組件初始化操做等。
import { Component, OnInit } from '@angular/core'; @Component({}) class ExampleComponent implements OnInit { constructor() {} // called on demand by Angular ngOnInit() { console.log('ngOnInit fired'); } } const instance = new ExampleComponent(); // Angular calls this when necessary instance.ngOnInit();