組件生命週期
constructor:構造器函數,一般用於注入服務
ngOnChanges:檢測到輸入數據變化,首次觸發發生在ngOnInit前。注意對象的屬性發生變化時監聽不到
ngOnInit:組件初始化,通常會設置一些初始值
ngDoCheck:手動觸發更新檢查
ngAfterContentInit:內容初始化到組件之後
ngAfterContentChecked:內容變更檢測之後
ngAfterViewInit:視圖 初始化之後
ngAfterViewChecked:視圖發生變化檢測之後,這個可以用來保證用戶視圖的及時更新
ngOnDestroy:組件註銷時的清理工作,通常用於移除事件監聽,退訂可觀察對象等
import { Component } from '@angular/core';
@Component({...})
export class AppComponent {
greeting:string = "Hello";//當這個對象變更時,會調用子組件的ngonchange鉤子
user:{name:string} = {name: "Tom"};
//當name變更時,不會調用子組件的ngonchange鉤子,因爲他變更的是name屬性而不是user對象。
constructor(){
}
}
<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)
- 所有的事件都會觸發變更檢測機制,不分原生還是自己寫的
- 所有帶有check字樣的鉤子都會這樣,只要有一點變動就會調用。除非這個組件被銷燬。(在兩個input框之間切換都回調用)
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("父組件投影內容初始化完畢");
this.message = "hello world";
}
ngAfterContentChecked(): void {
console.log("父組件投影內容變更檢測完畢");
}
ngAfterViewInit(): void {
console.log("父組件視圖內容初始化完畢");
}
子組件
ngAfterContentInit(): void {
console.log("子組件投影內容初始化完畢");
this.message = "hello world";
}
ngAfterContentChecked(): void {
console.log("子組件投影內容變更檢測完畢");
}
- 銷燬ngOnDestroy
- 在路由跳轉時會執行的鉤子。銷燬之前的組件。