Angular 2 constructor & ngOnInit

在 Angular 2 學習過程當中,相信不少初學者對 constructor 和 ngOnInit 的應用場景和區別會存在困惑,本文咱們會經過實際的例子,爲讀者一步步解開困惑。segmentfault

constructor

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

class AppComponent {
  constructor(name) {
    console.log('Constructor initialization');
    this.name = name;
  }
}

let appCmp = new AppComponent('AppCmp');
console.log(appCmp.name);

以上代碼運行後,控制檯的輸出結果:函數

Constructor initialization
AppCmp

接下來咱們看一下轉換後的 ES5 代碼:學習

var AppComponent = (function () {
    function AppComponent(name) {
        console.log('Constructor initialization');
        this.name = name;
    }
    return AppComponent;
}());

var appCmp = new AppComponent('AppCmp');
console.log(appCmp.name);

ngOnInit

ngOnInit 是 Angular 2 組件生命週期中的一個鉤子,Angular 2 中的全部鉤子和調用順序以下:this

  1. ngOnChanges - 當數據綁定輸入屬性的值發生變化時調用code

  2. ngOnInit - 在第一次 ngOnChanges 後調用component

  3. ngDoCheck - 自定義的方法,用於檢測和處理值的改變對象

  4. ngAfterContentInit - 在組件內容初始化以後調用繼承

  5. ngAfterContentChecked - 組件每次檢查內容時調用生命週期

  6. ngAfterViewInit - 組件相應的視圖初始化以後調用

  7. ngAfterViewChecked - 組件每次檢查視圖時調用

  8. 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 方法內能獲取到輸入的屬性。

constructor 應用場景

在 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 應用場景

在項目開發中咱們要儘可能保持構造函數簡單明瞭,讓它只執行簡單的數據初始化操做,所以咱們會把其餘的初始化操做放在 ngOnInit 鉤子中去執行。如在組件獲取輸入屬性以後,需執行組件初始化操做等。

我有話說

1.在ES6 或 TypeScript 中的 Class 是不會自動提高的

由於當 class 使用 extends 關鍵字實現繼承的時候,咱們不能確保所繼承父類的有效性,那麼就可能致使一些沒法預知的行爲。具體能夠參考 - Angular 2 Forward Reference 這篇文章。

2.TypeScrip 中 Class 靜態屬性和成員屬性的區別

AppComponent.ts

class AppComponent {
  static type: string = 'component';
  name: string;

  constructor() {
    this.name = 'AppComponent';
  }
}

轉化後的 ES5 代碼:

var AppComponent = (function () {
    function AppComponent() {
        this.name = 'AppComponent';
    }
    return AppComponent;
}());
AppComponent.type = 'component';

經過轉換後的代碼,咱們能夠知道類中的靜態屬性是屬於 AppComponent 構造函數的,而成員屬性是屬於 AppComponent 實例。

總結

在 Angular 2 中 constructor 通常用於依賴注入或執行簡單的數據初始化操做,ngOnInit 鉤子主要用於執行組件的其它初始化操做或獲取組件輸入的屬性值。

相關文章
相關標籤/搜索