Angualr4基礎之元件生命週期

風靈使發表於2018-08-26

元件生命週期

//這個順序是按照執行的先後排列的
constructor:構造器函式,一般用於注入服務
ngOnChanges:檢測到輸入資料變化,首次觸發發生在ngOnInit前。注意物件的屬性發生變化時監聽不到
ngOnInit:元件初始化,通常會設定一些初始值
ngDoCheck:手動觸發更新檢查 
ngAfterContentInit:內容初始化到元件之後
ngAfterContentChecked:內容變更檢測之後
ngAfterViewInit:檢視 初始化之後
ngAfterViewChecked:檢視發生變化檢測之後,這個可以用來保證使用者檢視的及時更新
ngOnDestroy:元件登出時的清理工作,通常用於移除事件監聽,退訂可觀察物件等

ngOnChanges

在父元件初始化或修改子元件的輸入引數時呼叫。

<!--父元件-->
import { Component } from '@angular/core';
@Component({...})
export class AppComponent {
  greeting:string  = "Hello";//當這個物件變更時,會呼叫子元件的ngonchange鉤子
  user:{name:string} = {name: "Tom"};
 //當name變更時,不會呼叫子元件的ngonchange鉤子,因為他變更的是name屬性而不是user物件。
  constructor(){
}
}
<!--html-->
<div class="parent">
  <h2>我是父元件</h2>
  <div>
    問候語:<input type="text" [(ngModel)]="greeting">//雙向繫結
  </div>
  <div>
    姓名:<input type="text" [(ngModel)]="user.name">//雙向繫結
  </div>
  <app-child [greeting]="greeting" [user]="user"></app-child>//將值傳入子元件,當值改變時會呼叫子元件的ngonchange鉤子
</div>

變更檢測 ngDoCheck (依賴於zone.js)

  • Default策略
  • OnPush策略

所有的事件都會觸發變更檢測機制,不分原生還是自己寫的
所有帶有check字樣的鉤子都會這樣,只要有一點變動就會呼叫。除非這個元件被銷燬。(在兩個input框之間切換都回撥用)

//跟上邊的程式碼一樣,但是當name改變時,也會呼叫ngDoCheck方法鉤子。
import {Component, OnInit, Input, OnChanges, SimpleChanges, DoCheck} from '@angular/core';
@Component({
  selector: 'app-child',
  templateUrl: './child.component.html',
  styleUrls: ['./child.component.css']
})
export class ChildComponent implements OnInit, OnChanges, DoCheck {
  @Input()
  greeting:string;
  @Input()
  user:{name:string};
  message:string = "初始化訊息";
  oldUsername:string;
  changeDetected:boolean = false;
  noChangeCount:number = 0;
  constructor() { }
  ngOnInit() {
  }
  ngOnChanges(changes: SimpleChanges): void {
    console.log(JSON.stringify(changes, null, 2));
  }
  ngDoCheck(): void {//子元件裡的變更檢測,
    if(this.user.name !== this.oldUsername) {
      this.changeDetected = true;
      console.log("DoCheck:user.name從"+this.oldUsername+"變為"+this.user.name);
      this.oldUsername = this.user.name;
    }
    if(this.changeDetected) {
      this.noChangeCount = 0;
    }else{
      this.noChangeCount = this.noChangeCount + 1;
      console.log("DoCheck:user.name沒變化時ngDoCheck方法已經被呼叫"+this.noChangeCount+"次")
    }
    this.changeDetected = false;
  }
}

View鉤子

在父元件裡可以通過@ViewChild獲得子元件的引用。呼叫子元件方法

<!--父元件-->
import {Component, OnInit, ViewChild, AfterViewInit, AfterViewChecked} from "@angular/core";
import {ChildComponent} from "./child/child.component";
@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit, AfterViewInit,
  @ViewChild("child1")//引入子元件
  child1:ChildComponent;//定義子元件物件
  message:string;
  constructor(){
  }
  ngAfterViewInit(): void {//要想執行這個,必須等子元件全部載入完畢。
    console.log("父元件的檢視初始化完畢");
  //在ngAfterViewInit裡邊不能寫賦值等操作,要想進行這些操作必須寫在settimeout裡邊
    setTimeout(() => {   
      this.message = "Hello";
    },0);
  }
  ngAfterViewChecked(): void {
    console.log("父元件的檢視變更檢測完畢");
  }
  ngOnInit(): void {
    setInterval(() => {
      this.child1.greeting("Tom");//呼叫子元件裡的方法
    }, 5000);
  }
<!--子元件-->
import {Component, OnInit, AfterViewChecked, AfterViewInit} from '@angular/core';
@Component({
  selector: 'app-child',
  templateUrl: './child.component.html',
  styleUrls: ['./child.component.css']
})
export class ChildComponent implements OnInit, AfterViewInit,
  AfterViewChecked {
  ngAfterViewInit(): void {
    console.log("子元件的檢視初始化完畢");
  }
  ngAfterViewChecked(): void {
    console.log("子元件的檢視變更檢測完畢");
  }
  constructor() { }
  ngOnInit() {
  }
  greeting(name:string) {
    console.log("hello "+name);
  }
}

ngConent指令

ngConent指令用於子元件,可以將父元件的內容投影到子元件

<!--父元件-->
<app-child>
<div class="header">這是頭部,這個div是父元件投影到子元件的</div
<div class="footer">這是底部,這個div是父元件投影到子元件的</div>
</app-child>
<!--子元件-->
<ng-content select=".header"></ng-content>
<ng-content select=".footer"></ng-content>

AfterContentInit,AfterContentChecked, AfterViewInit

//父元件
//在這裡邊可以對屬性內容進行變更
ngAfterContentInit(): void {
    console.log("父元件投影內容初始化完畢");//1
    this.message = "hello world";
  }

  ngAfterContentChecked(): void {
    console.log("父元件投影內容變更檢測完畢");//2
  }

  ngAfterViewInit(): void {
    console.log("父元件檢視內容初始化完畢");//5
  }
  子元件
  ngAfterContentInit(): void {
    console.log("子元件投影內容初始化完畢");//3
    this.message = "hello world";
  }

  ngAfterContentChecked(): void {
    console.log("子元件投影內容變更檢測完畢");//4
  }

銷燬ngOnDestroy

在路由跳轉時會執行的鉤子。銷燬之前的元件。

相關文章