當(dāng) Angular 實例化組件類 并渲染組件視圖及其子視圖時,組件實例的生命周期就開始了。生命周期一直伴隨著變更檢測,Angular 會檢查數(shù)據(jù)綁定屬性何時發(fā)生變化,并按需更新視圖和組件實例。當(dāng) Angular 銷毀組件實例并從 DOM 中移除它渲染的模板時,生命周期就結(jié)束了。當(dāng) Angular 在執(zhí)行過程中創(chuàng)建、更新和銷毀實例時,指令就有了類似的生命周期。
你的應(yīng)用可以使用生命周期鉤子方法來觸發(fā)組件或指令生命周期中的關(guān)鍵事件,以初始化新實例,需要時啟動變更檢測,在變更檢測過程中響應(yīng)更新,并在刪除實例之前進行清理。
- 淺灰色名字的事件,在組件的生命周期中只會觸發(fā)一次,而綠色的隨著相應(yīng)的邏輯變化會多次觸發(fā)。
Construction, OnChanges, OnInit, DoCheck, AfterContentInit, AfterContentChecked, AfterViewInit, AfterViewChecked, OnDestroy
1 響應(yīng)生命周期事件
可以通過實現(xiàn)一個或多個 Angular core
庫中定義的生命周期鉤子接口來響應(yīng)組件或指令生命周期中的事件。這些鉤子讓你有機會在適當(dāng)?shù)臅r候?qū)M件或指令實例進行操作,比如 Angular 創(chuàng)建、更新或銷毀這個實例時。
每個接口都有唯一的一個鉤子方法,它們的名字是由接口名再加上 ng 前綴構(gòu)成的。比如,OnInit 接口的鉤子方法叫做 ngOnInit()。如果你在組件或指令類中實現(xiàn)了這個方法,Angular 就會在首次檢查完組件或指令的輸入屬性后,緊接著調(diào)用它。
1.1 constructor()
每一個組件文件,本質(zhì)上都是一個類,而constructor是ES6引入類的概念后新出現(xiàn)的東西,是類的自身屬性,所以并非Angular的鉤子,constructor的主要作用是注入依賴,這里就不展開了。這是最先被調(diào)用的一個函數(shù)。Angular 在實例化組件類時執(zhí)行,可以用來接收 Angular 注入的服務(wù)實例對象。
import {Component} from '@angular/core';
// 引入服務(wù)
import {StorageService} from '../../services/storage.service'
@Component({
selector: 'app-life',
templateUrl: './life.component.html',
styleUrls: ['./life.component.scss']
})
export class LifeComponent {
constructor(public StorageService: StorageService) {
console.log('init StorageService', this.StorageService)
}
}
1.2 ngOnChanges()
注意這里解釋一下什么是輸入屬性?如下:
Angular的輸入屬性是指帶**有@Input()**裝飾器的可設(shè)置屬性,它允許父組件將數(shù)據(jù)值發(fā)送到子組件中。具體來說,父組件通過綁定屬性到子組件,子組件則利用@Input()裝飾器來標(biāo)識這是一個輸入變量屬性。
一旦檢測到該組件或指令的輸入屬性發(fā)生了變化,Angular 就會調(diào)用它的 ngOnChanges() 方法。這個 onChanges 范例通過監(jiān)控 OnChanges() 鉤子演示了這一點。
如下例子所示:
父組件:
<app-life [parentValue]="parentValue"></app-life>
<input type="text" name="parentValue" [(ngModel)]="parentValue">
子組件:
import {Component, Input, SimpleChanges} from '@angular/core';
// 引入服務(wù)
import {StorageService} from '../../services/storage.service'
@Component({
selector: 'app-life',
templateUrl: './life.component.html',
styleUrls: ['./life.component.scss']
})
export class LifeComponent {
constructor(public StorageService: StorageService) {
console.log('init StorageService', this.StorageService)
}
@Input() parentValue: string;
ngOnChanges(changes: SimpleChanges) {
console.log(changes)
for (const propName in changes) {
const chng = changes[propName];
const cur = JSON.stringify(chng.currentValue);
const prev = JSON.stringify(chng.previousValue);
console.log('cur = ', cur)
console.log('prev = ', prev)
}
}
}
當(dāng)輸入屬性的值發(fā)生變化時:
ngOnChanges() 方法獲取了一個對象,它把每個發(fā)生變化的屬性名都映射到了一個SimpleChange對象,該對象中有屬性的當(dāng)前值和前一個值。這個鉤子會在這些發(fā)生了變化的屬性上進行迭代,并記錄它們。
1.3 ngOnInit()
通常我們在這里獲取數(shù)據(jù)或者設(shè)置屬性值。
ngOnInit() {
this.getUserDataByAPIRequest();
this.setOtherData();
this.age = 18;
}
使用 ngOnInit() 方法執(zhí)行以下初始化任務(wù):
-
在構(gòu)造函數(shù)外部執(zhí)行復(fù)雜的初始化。**組件的構(gòu)造應(yīng)該既便宜又安全。比如,你不應(yīng)該在組件構(gòu)造函數(shù)中獲取數(shù)據(jù)。**當(dāng)在測試中創(chuàng)建組件時或者決定顯示它之前,你不應(yīng)該擔(dān)心新組件會嘗試聯(lián)系遠程服務(wù)器。ngOnInit()是組件獲取初始數(shù)據(jù)的好地方。
你固然可以在構(gòu)造函數(shù)中調(diào)用getHeroes(),但那不是最佳實踐。讓構(gòu)造函數(shù)保持簡單,只做最小化的初始化操作,比如把構(gòu)造函數(shù)的參數(shù)賦值給屬性。構(gòu)造函數(shù)不應(yīng)該做任何事。它當(dāng)然不應(yīng)該調(diào)用某個函數(shù)來向遠端服務(wù)(比如真實的數(shù)據(jù)服務(wù))發(fā)起HTTP 請求。而是選擇在 ngOnInit 生命周期鉤子中調(diào)用 getHeroes(),之后 Angular 會在構(gòu)造出HeroesComponent 的實例之后的某個合適的時機調(diào)用 ngOnInit()。
ngOnInit(): void {
this.getHeroes();
}
-
在 Angular設(shè)置好輸入屬性之后設(shè)置組件。構(gòu)造函數(shù)應(yīng)該只把初始局部變量設(shè)置為簡單的值。請記住,只有在構(gòu)造完成之后才會設(shè)置指令的數(shù)據(jù)綁定輸入屬性。如果要根據(jù)這些屬性對指令進行初始化,請在運行ngOnInit() 時設(shè)置它們。
ngOnChanges() 方法是你能訪問這些屬性的第一次機會。Angular 會在調(diào)用 ngOnInit() 之前調(diào)用
ngOnChanges(),而且之后還會調(diào)用多次。但它只調(diào)用一次 ngOnInit()。
1.4 ngDoCheck()
這種情況不常見,如果是新手也沒必要在這上面?zhèn)X筋,只需要知道它會在ngOnInit()和每次ngOnChanges()之后調(diào)用。
ngDoCheck() {
console.log('ngOnInit()和每次ngOnChanges()之后調(diào)用')
}
1.5 ngAfterContentInit()
它會在 Angular 初始化完該指令的所有內(nèi)容之后立即調(diào)用。要點:
- 在指令初始化完成之后,它只會調(diào)用一次。
- 可以用來處理一些初始化任務(wù)。
1.6 ngAfterContentChecked()
在默認(rèn)的變更檢測器對該指令下的所有內(nèi)容完成了變更檢測之后立即調(diào)用。
1.7 ngAfterViewInit()
簡單來說就是當(dāng)組件視圖渲染完成后調(diào)用,也就是說在這個函數(shù)執(zhí)行之前是沒有辦法獲取到HTML里面的內(nèi)容的。舉個例子,我們想獲取視圖里的一個div結(jié)點, 可以通過ViewChild, 然后嘗試在ngOnInit和ngAfterViewInit中去打印。
<app-life [parentValue]="parentValue" #lifeComponent></app-life>
import {Component, ViewChild} from '@angular/core';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss']
})
export class AppComponent {
title = 'firstProject';
public parentValue: string = 'parentValue'
@ViewChild('lifeComponent') lifeComponent: any;
ngOnInit(): void {
console.log('ngOnInit', this.lifeComponent);
}
ngAfterViewInit(): void {
console.log('ngAfterViewInit', this.lifeComponent);
}
}
1.8 ngAfterViewChecked()
<app-life [parentValue]="parentValue" #lifeComponent></app-life>
<input type="text" name="parentValue" [(ngModel)]="parentValue">
import {Component, ViewChild} from '@angular/core';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss']
})
export class AppComponent {
title = 'firstProject';
public parentValue: string = 'parentValue'
@ViewChild('lifeComponent') lifeComponent: any;
ngOnInit(): void {
console.log('ngOnInit', this.lifeComponent);
}
ngAfterViewInit(): void {
console.log('ngAfterViewInit', this.lifeComponent);
}
ngAfterViewChecked(): void {
console.log('ngAfterViewChecked', this.lifeComponent);
}
}
文章來源:http://www.zghlxwxcb.cn/news/detail-743352.html
1.9 ngOnDestroy()
文章來源地址http://www.zghlxwxcb.cn/news/detail-743352.html
到了這里,關(guān)于Angular組件生命周期詳解的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!