constructor 與 ngOnInit

2018-08-28 10:28 更新

查看新版Angular constructor vs ngOnInit

在 Angular 學習過程中,相信很多初學者對 constructor 和 ngOnInit 的應用場景和區(qū)別會存在困惑,本文我們會通過實際的例子,為讀者一步步解開困惑。

constructor

在 ES6 中就引入了類,constructor(構造函數(shù)) 是類中的特殊方法,主要用來做初始化操作,在進行類實例化操作時,會被自動調用。馬上來個例子:

  1. class AppComponent {
  2. constructor(name) {
  3. console.log('Constructor initialization');
  4. this.name = name;
  5. }
  6. }
  7. let appCmp = new AppComponent('AppCmp');
  8. console.log(appCmp.name);

以上代碼運行后,控制臺的輸出結果:

  1. Constructor initialization
  2. AppCmp

接下來我們看一下轉換后的 ES5 代碼:

  1. var AppComponent = (function () {
  2. function AppComponent(name) {
  3. console.log('Constructor initialization');
  4. this.name = name;
  5. }
  6. return AppComponent;
  7. }());
  8. var appCmp = new AppComponent('AppCmp');
  9. console.log(appCmp.name);

ngOnInit

ngOnInit 是 Angular 組件生命周期中的一個鉤子,Angular 中的所有鉤子和調用順序如下:

  1. ngOnChanges - 當數(shù)據(jù)綁定輸入屬性的值發(fā)生變化時調用
  2. ngOnInit - 在第一次 ngOnChanges 后調用
  3. ngDoCheck - 自定義的方法,用于檢測和處理值的改變
  4. ngAfterContentInit - 在組件內容初始化之后調用
  5. ngAfterContentChecked - 組件每次檢查內容時調用
  6. ngAfterViewInit - 組件相應的視圖初始化之后調用
  7. ngAfterViewChecked - 組件每次檢查視圖時調用
  8. ngOnDestroy - 指令銷毀前調用

其中 ngOnInit 用于在 Angular 獲取輸入屬性后初始化組件,該鉤子方法會在第一次 ngOnChanges 之后被調用。

另外需要注意的是 ngOnInit 鉤子只會被調用一次,我們來看一下具體示例:

  1. import { Component, OnInit } from '@angular/core';
  2. @Component({
  3. selector: 'my-app',
  4. template: `
  5. <h1>Welcome to Angular World</h1>
  6. <p>Hello {{name}}</p>
  7. `,
  8. })
  9. export class AppComponent implements OnInit {
  10. name: string = '';
  11. constructor() {
  12. console.log('Constructor initialization');
  13. this.name = 'Semlinker';
  14. }
  15. ngOnInit() {
  16. console.log('ngOnInit hook has been called');
  17. }
  18. }

以上代碼運行后,控制臺的輸出結果:

  1. Constructor initialization
  2. ngOnInit hook has been called

接下來我們再來看一個 父 - 子組件傳參的例子:

parent.component.ts

  1. import { Component } from '@angular/core';
  2. @Component({
  3. selector: 'exe-parent',
  4. template: `
  5. <h1>Welcome to Angular World</h1>
  6. <p>Hello {{name}}</p>
  7. <exe-child [pname]="name"></exe-child>
  8. `,
  9. })
  10. export class ParentComponent {
  11. name: string = '';
  12. constructor() {
  13. this.name = 'Semlinker';
  14. }
  15. }

child.component.ts

  1. import { Component, Input, OnInit } from '@angular/core';
  2. @Component({
  3. selector: 'exe-child',
  4. template: `
  5. <p>父組件的名稱:{{pname}} </p>
  6. `
  7. })
  8. export class ChildComponent implements OnInit {
  9. @Input()
  10. pname: string; // 父組件的名稱
  11. constructor() {
  12. console.log('ChildComponent constructor', this.pname); // Output:undefined
  13. }
  14. ngOnInit() {
  15. console.log('ChildComponent ngOnInit', this.pname);
  16. }
  17. }

以上代碼運行后,控制臺的輸出結果:

  1. ChildComponent constructor undefined
  2. ChildComponent ngOnInit Semlinker

我們發(fā)現(xiàn)在 ChildComponent 構造函數(shù)中,是無法獲取輸入屬性的值,而在 ngOnInit 方法中,我們能正常獲取輸入屬性的值。因為 ChildComponent 組件的構造函數(shù)會優(yōu)先執(zhí)行,當 ChildComponent 組件輸入屬性變化時會自動觸發(fā) ngOnChanges 鉤子,然后在調用 ngOnInit 鉤子方法,所以在 ngOnInit 方法內能獲取到輸入的屬性。

constructor 應用場景

在 Angular 中,構造函數(shù)一般用于依賴注入或執(zhí)行一些簡單的初始化操作。

  1. import { Component, ElementRef } from '@angular/core';
  2. @Component({
  3. selector: 'my-app',
  4. template: `
  5. <h1>Welcome to Angular World</h1>
  6. <p>Hello {{name}}</p>
  7. `,
  8. })
  9. export class AppComponent {
  10. name: string = '';
  11. constructor(public elementRef: ElementRef) { // 使用構造注入的方式注入依賴對象
  12. this.name = 'Semlinker'; // 執(zhí)行初始化操作
  13. }
  14. }

ngOnInit 應用場景

在項目開發(fā)中我們要盡量保持構造函數(shù)簡單明了,讓它只執(zhí)行簡單的數(shù)據(jù)初始化操作,因此我們會把其他的初始化操作放在 ngOnInit 鉤子中去執(zhí)行。如在組件獲取輸入屬性之后,需執(zhí)行組件初始化操作等。

我有話說

在ES6 或 TypeScript 中的 Class 是不會自動提升的

因為當 class 使用 extends 關鍵字實現(xiàn)繼承的時候,我們不能確保所繼承父類的有效性,那么就可能導致一些無法預知的行為。具體可以參考 - Angular 2 Forward Reference 這篇文章。

TypeScrip 中 Class 靜態(tài)屬性和成員屬性的區(qū)別

AppComponent.ts

  1. class AppComponent {
  2. static type: string = 'component';
  3. name: string;
  4. constructor() {
  5. this.name = 'AppComponent';
  6. }
  7. }

轉化后的 ES5 代碼:

  1. var AppComponent = (function () {
  2. function AppComponent() {
  3. this.name = 'AppComponent';
  4. }
  5. return AppComponent;
  6. }());
  7. AppComponent.type = 'component';

通過轉換后的代碼,我們可以知道類中的靜態(tài)屬性是屬于 AppComponent 構造函數(shù)的,而成員屬性是屬于 AppComponent 實例。

總結

在 Angular 中 constructor 一般用于依賴注入或執(zhí)行簡單的數(shù)據(jù)初始化操作,ngOnInit 鉤子主要用于執(zhí)行組件的其它初始化操作或獲取組件輸入的屬性值。

以上內容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號