Angular Lifecycle Hooks 執行順序示意圖

← INSIGHTS & PERSPECTIVES | 前端開發

Angular Lifecycle Hooks 教學:生命週期鉤子順序與使用時機

整理 Angular Lifecycle Hooks 的生命週期概念、ngOnChanges、ngOnInit、ngDoCheck、AfterContent、AfterView 與 ngOnDestroy 的呼叫順序和使用場景。

Angular Lifecycle Hooks 是 Angular 在 component 或 directive 建立、更新、檢查、顯示內容、顯示 view、銷毀之前提供的掛點。開發者可以在 `ngOnInit()` 初始化資料、在 `ngOnChanges()` 追蹤輸入變化、在 `ngOnDestroy()` 清理訂閱與事件,避免把所有邏輯都塞進 constructor 或 template。

Angular Lifecycle Hooks 執行順序示意圖

Angular Lifecycle Hooks 是什麼?

Angular Lifecycle Hooks 是 component 與 directive 生命週期中的 callback method。Angular 會管理建立、資料綁定檢查、內容投影、view 初始化與銷毀流程,並在特定階段呼叫對應 hook。

一個 component 有一段由 Angular 管理的生命週期。Angular 會建立 component、產生畫面,當資料綁定屬性改變時做檢查;當 component 從 DOM 中移除之前,Angular 也會銷毀該 component。

Lifecycle Hooks 的用途,就是讓開發者在這些階段加入需要執行的程式。例如資料初始化、手動變更偵測、讀取 projected content、讀取 view children,或在離開畫面前取消訂閱 Observables 和事件處理程序。

Angular Lifecycle Hooks 怎麼使用?

Angular Lifecycle Hooks 通常透過實作對應 TypeScript interface,再在 component class 中加入同名 method。`OnInit` 對應 `ngOnInit()`,`OnChanges` 對應 `ngOnChanges()`。

以下是一個簡化後的 `OnInit` 使用範例。`PeekABoo` component 實作 `OnInit`,Angular 初始化 component 後會呼叫 `ngOnInit()`,因此 log 會在初始化階段被寫入。

```ts

export class PeekABoo implements OnInit {

constructor(private logger: LoggerService) {}

ngOnInit() {

this.logIt('OnInit');

}

logIt(msg: string) {

this.logger.log(`#${nextId++} ${msg}`);

}

}

```

實作 interface 不是執行 hook 的必要條件;只要 class 上有符合名稱的 method,Angular 仍會呼叫。實作 interface 的好處是讓 TypeScript 幫忙檢查拼字與方法簽名,少一點看不見的錯。

Angular Lifecycle Hooks 的呼叫順序是什麼?

Angular Lifecycle Hooks 的常見順序是 `ngOnChanges()`、`ngOnInit()`、`ngDoCheck()`、content hooks、view hooks,最後才是 `ngOnDestroy()`。其中 `ngOnChanges()` 只會在有 input 變化時出現。

Hook目的和呼叫時機
`ngOnChanges()`Angular 設定資料綁定的 input property 後呼叫。這個 method 接收 `SimpleChanges`,可取得目前值與前一次的值;初始化時會在 `ngOnInit()` 之前呼叫。
`ngOnInit()`Angular 初始化 directive 或 component,並設定第一次顯示所需的 input property 後呼叫。適合放初始化資料、呼叫 service 載入資料等工作。
`ngDoCheck()`Angular 每次檢查 component 變化時呼叫。適合處理 Angular 無法自行偵測、但開發者需要手動追蹤的變化。
`ngAfterContentInit()`Angular 將外部 projected content 設定到 component 後呼叫一次。常見於使用 `<ng-content>` 的 component。
`ngAfterContentChecked()`Angular 檢查投影到 component 裡的 content 後呼叫。這個 hook 可能頻繁執行,不適合放昂貴運算。
`ngAfterViewInit()`Angular 初始化 component template 與 child views 後呼叫一次。常見於需要讀取 view children 或 DOM 相關狀態時。
`ngAfterViewChecked()`Angular 檢查 component view 與 child views 後呼叫。這個 hook 也可能頻繁執行,使用時要注意效能。
`ngOnDestroy()`Angular 銷毀 directive 或 component 前呼叫。適合取消 Observables 訂閱、解除事件處理程序、停止 timer,避免記憶體洩漏。

Angular 官方文件把 component lifecycle 定義為從建立到銷毀之間的一連串步驟;每個 hook 都對應 Angular rendering 與 change detection 流程中的一個時間點(Angular Docs,存取日期 2026-08-28)。

ngOnChanges 和 ngOnInit 差在哪?

`ngOnChanges()` 用來回應 input property 的變化,`ngOnInit()` 用來做 component 第一次初始化。初始化階段如果 component 有 input,Angular 會先呼叫 `ngOnChanges()`,再呼叫 `ngOnInit()`。

開發時可以用這個方式判斷:

需求適合的 hook
需要比較 input 的前後值`ngOnChanges()`
需要在 component 第一次準備好時載入資料`ngOnInit()`
只想初始化本地狀態,不依賴 input 變化歷程`ngOnInit()`
input 每次改變都要重新計算畫面資料`ngOnChanges()`

`ngOnChanges()` 會收到 `SimpleChanges` object,裡面包含每個變更屬性的 previous value、current value,以及是否為 first change。`ngOnInit()` 則只會在 component 初始化時執行一次,不負責追蹤後續 input 變化。

ngDoCheck 什麼時候才需要用?

`ngDoCheck()` 適合用在 Angular 預設變更偵測無法完整判斷的情境。一般 component 不需要主動實作 `ngDoCheck()`,因為這個 hook 會很頻繁地被呼叫。

如果資料變化已經能透過 input、event、Observable 或 signal 表達,通常不需要 `ngDoCheck()`。`ngDoCheck()` 比較像最後的手動檢查點:當外部物件被原地修改、第三方程式庫改動狀態,或需要自訂差異比對時,才考慮使用。

實務上,`ngDoCheck()` 裡的程式要非常輕。把 API 呼叫、複雜排序、大量 DOM 操作放在這裡,容易讓每一次 change detection 都變慢。

AfterContent 和 AfterView Hooks 差在哪?

AfterContent hooks 針對投影進 component 的外部內容,AfterView hooks 針對 component 自己的 template 與 child views。兩者差別在於 Angular 當下檢查的是 content 還是 view。

`ngAfterContentInit()` 與 `ngAfterContentChecked()` 對應 projected content,例如父層透過 `<ng-content>` 塞進子 component 的內容。這組 hooks 關心的是「外部放進來的內容」。

`ngAfterViewInit()` 與 `ngAfterViewChecked()` 對應 component 自己 template 裡宣告的 view,以及 template 裡的 child components。這組 hooks 關心的是「component 自己長出來的畫面」。

如果只是初始化資料,通常先從 `ngOnInit()` 開始。只有真的需要讀取 content children、view children 或 DOM 狀態時,再使用 AfterContent / AfterView hooks,程式意圖會更清楚。

ngOnDestroy 為什麼重要?

`ngOnDestroy()` 是 component 或 directive 被銷毀前的清理點。只要 component 裡有訂閱、timer、手動事件監聽或外部資源,就應該在 `ngOnDestroy()` 清掉。

最常見的例子是 Observables 和事件處理程序。如果 component 已經離開畫面,訂閱卻還在背景接收資料,就可能造成記憶體洩漏,甚至讓已不存在的 view 繼續嘗試更新。

早期 Angular 教學常會直接在 `ngOnDestroy()` 裡取消訂閱。新版本 Angular 也提供 `DestroyRef` 等寫法,可以把 setup 和 cleanup 放得更近;不管使用哪一種寫法,核心目標都是在 component 離開時停止不該繼續跑的工作。

Peek-a-boo 範例可以觀察什麼?

Peek-a-boo 範例適合用來觀察 Angular Lifecycle Hooks 的實際呼叫順序。範例會在每個 hook 被呼叫時寫入 log,讓開發者看到 component 從建立到銷毀的過程。

原本學 Lifecycle Hooks 時,最抽象的地方不是 hook 名稱,而是「Angular 到底什麼時候呼叫」。Peek-a-boo 範例把每個 callback 都印出來,因此可以直接看到初始化、檢查與銷毀的順序。

Angular Peek-a-boo lifecycle hooks 範例執行結果

練習時可以先從官方 lifecycle 範例開始,再試著加入 input property、切換 component 顯示狀態、訂閱一個 Observable。這樣會更容易理解 `ngOnChanges()`、`ngOnInit()` 和 `ngOnDestroy()` 分別處理哪一段責任。

常見問題

QAngular Lifecycle Hooks 一定只能用在 component 嗎?

不是。Angular directive 也有相同的 lifecycle hooks。只要 directive 有對應生命週期需求,例如初始化、追蹤 input 變化或銷毀前清理,就可以使用對應 hook。

Qconstructor 和 ngOnInit 有什麼差別?

constructor 是 TypeScript class 被建立時執行,主要適合做 dependency injection 和非常單純的初始設定。`ngOnInit()` 是 Angular 完成 input 初始化後呼叫,比較適合放依賴 Angular 綁定結果的初始化邏輯。

QngOnChanges 為什麼會比 ngOnInit 早執行?

初始化 component 時,Angular 需要先把 input property 設定進 component,才能讓 component 根據輸入值做初始化。因此第一次 `ngOnChanges()` 會在 `ngOnInit()` 之前執行。

QngAfterViewInit 可以直接改畫面狀態嗎?

`ngAfterViewInit()` 適合讀取 view 初始化後的狀態,但不適合隨意改動會影響 template 綁定的資料。若在檢查流程中改變狀態,可能遇到 `ExpressionChangedAfterItHasBeenCheckedError`。

QngOnDestroy 通常要清理哪些東西?

`ngOnDestroy()` 通常清理 Observable 訂閱、DOM event listener、`setInterval`、`setTimeout`、WebSocket 或第三方 library 建立的資源。判斷原則是:component 離開畫面後還會繼續執行或占用資源的東西,都要清掉。

延伸閱讀

參考資料

最後更新

2026-08-28

關於作者 {#author}

Claire Chang | 企業 AI 導入與流程轉型顧問。專注於 AI Agent 架構設計、ERP 系統整合與企業 AI 治理。

首次發布:2017-12-29