angular4 組件生命週期

紅色的被調用一次綠色的會被調用屢次,變化檢測中的四個方法和組件初始化中的四個方法是同樣的。css

組件初始化:前面四個初始化屬性,後面四個渲染視圖html

變動檢測:使屬性值和頁面展現保持一致。java

組件生命週期順序:
1.constructor:構造器函數,實例化對象,並用於注入服務
2.ngOnChanges初始化 輸入屬性,檢測到@Input輸入數據變化時執行,首次觸發發生在ngOnInit前。注意對象的屬性發生變化時監聽不到
3.ngOnInit初始化 除輸入屬性以外其餘的屬性,一般會設置一些初始值(若是初始化的邏輯須要依賴@Input輸入屬性,那就必定要寫在ngOnInit中,而不要寫在構造函數中)
4.ngDoCheck組件變動檢測時執行
5.ngAfterContentInit投影內容 初始化到組件以後執行
6.ngAfterContentChecked投影內容 變動檢測以後執行
7.ngAfterViewInit視圖 初始化以後執行
8.ngAfterViewChecked視圖 發生變化檢測以後執行,這個能夠用來保證用戶視圖的及時更新
9.ngOnDestroy:組件註銷時的清理工做,一般用於移除事件監聽,退訂可觀察對象等json

 

 

1.onChanges瀏覽器

@input屬性(輸入屬性)發生變化時,會調用;當輸入屬性爲對象時,當對象的屬性值發生變化時,不會調用,當對象的引用變化時會觸發。app

例子:函數

child.ts代碼片斷:this

@Input()
greeting: string;

@Input()
user:{name:string};

如上,greeting改變會觸發ngOnChanges事件,而user.name改變不會觸發ngOnChanges事件,由於greeting是字符串是不可變對象(每次值改變的時候都會建立一個新的字符串,而後把引用指向新的字符串),而user是可變對象,修改姓名的值的時候並無改變user對象的引用。那麼怎麼監控可變對象呢,用doCheck。spa

 

2.變動檢測機制code

angular使用package.json文件中dependencies引入的zone.js來實現變動檢測機制。

保證屬性的變化和頁面的變化是一致的,瀏覽器中發生的任何變化都會觸發變動檢測機制,好比點擊按鈕,輸入數據。。。 

Default策略:默認,無論變動發生在哪一個組件上,zone都會檢測整個組件樹

OnPush策略:若是有某個組件聲明自身的策略爲onPush,只有當這個組件的@input輸入屬性發生變化時,zone纔會檢測該組件及其子組件

例子:

  變動檢測機制的實現須要實現DoCheck接口中的ngDoCheck()方法。頁面上隨便一個點擊都會觸該方法,好比點擊輸入框等,全部在使用上要很是當心。

import {Component, OnInit,Input,,DoCheck} from '@angular/core';

@Component({
  selector: 'app-child',
  templateUrl: './child.component.html',
  styleUrls: ['./child.component.css']
})
export class ChildComponent implements DoCheck{
  constructor() {}

  ngDoCheck():void{
     //組件變動時觸發
  }
}

 須要注意的是,當變動檢測機制發生的時候,不光是doCheck()方法全部含check關鍵字的方法(包括ngAfterContentChecked(),ngAfterViewChecked())都會被調用。因此這些方法也都要很是當心的使用。

 

3.view鉤子

1.父組件調用子組件的方法

child.component.ts

import { Component, OnInit } from '@angular/core';

@Component({
  selector: 'app-child',
  templateUrl: './child.component.html',
  styleUrls: ['./child.component.css']
})
export class ChildComponent implements OnInit {

  constructor() { }

  ngOnInit() {}
 //子組件方法
  greeting(name:string){
    console.log("hello"+name);
  }
}

方法一:在模板中經過對子組件標籤的模板變量( #變量名)直接調用用子組件方法:

parent.component.html

<!--定義模板變量child1-->
<app-child #child1></app-child>
<app-child #child2></app-child>
<!--在模板中調用子組件greeting()方法-->
<button (click)="child2.greeting('Jerry')"></button>

方法二:在組件類中經過@ViewChild裝飾器聲明子組件的對象,而後調用子組件對象中的方法

parent.component.ts

import { Component,ViewChild } from '@angular/core';
import {ChildComponent} from "./child/child.component";

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {

  //經過@ViewChild獲取的子組件對象
  @ViewChild("child1")
  child1:ChildComponent 

  constructor(){}

  ngOnInit():void{
    this.child1.greeting("Tom");//調用方法
  }
}

2.AfterViewInit和AfterViewChecked

在整個組件模板的內容顯示完成,即都已經呈現給用戶看以後,會調用這兩個方法;

初始化方法AfterViewInit()優先被調用,並且只調用一次AfterViewChecked後調用;

若是存在子組件,則先調用子組件的,再調用父組件的;

 

不要在這兩個方法中去改變視圖中綁定的東西,若是想改變也要寫在一個setTimeout裏邊,以下:

  例子中,整個視圖已經初始化完畢了,又要去修改與視圖有綁定的message,會報錯,

message:string;

ngAfterViewInit(): void {
    console.log("父組件的視圖初始化完畢");
    this.message="Hello";
}

改爲:

ngAfterViewInit(): void {
    console.log("父組件的視圖初始化完畢");
    setTimeout(()=>{
      this.message="Hello";
    },0);
  }

在javaScript另外一個運行週期去運行

 

4.ngContent

ngContent指令用來將父組件模板中的任意html片斷投影到子組件中

例子:

child.html

<div>
  <h2>子組件</h2>
  <ng-content select=".header"></ng-content>
  <ng-content select=".footer"></ng-content>
</div>

parent.html

<div>
  <h2>父組件</h2>
  <app-child>
    <div class="header">頁頭</div>
    <div class="footer">頁腳</div>
  </app-child>
</div>

如上,子組件經過<ng-content>指令select屬性,分別將父組件的頁頭和頁腳兩個div投影到子組件中。

ngAfterContentInitngAfterContentChecked在投影的模板被渲染以後調用。

 

5.ngOnDestroy

從A路由跳到B路由後,A路由對應的組件會執行ngOnDestroy

相關文章
相關標籤/搜索