了解 Blazor 元件生命週期
Blazor 元件具有定義完善的生命週期,會在第一次建立時開始,並在終結時結束。 元件生命週期是由發生以回應特定觸發的一組事件所控管。 這類觸發包括要初始化的元件、與元件互動的使用者,或元件所在要關閉的頁面。
在此單元中,您將了解 Blazor 元件生命週期期間發生的事件。 您將了解如何處理這些事件,以最佳化完成的工作,並提高 Blazor 頁面的回應能力。
Blazor 元件生命週期
Blazor 元件代表 Blazor 應用程式中的檢視,其會定義版面配置和 UI 邏輯。 元件會在應用程式執行時產生 HTML 標記。 使用者互動事件可以觸發自訂代碼,而且可以更新元件以重新轉譯顯示。 在頁面關閉時,Blazor 會移除元件並清除任何資源。 當使用者返回頁面,就會建立新的執行個體。
下圖說明元件存留期內發生的事件,以及可用來處理這些事件的方法。 除了 SetParametersAsync
以外,Blazor 會提供每個方法的同步和非同步版本。
所有 Blazor 元件都源自 ComponentBase 類別或定義顯示的方法並提供預設行為的 IComponent。 您可以透過覆寫對應的方法來處理事件。
雖然圖表顯示生命週期方法之間有單一執行緒流程,但這些方法的非同步版本仍可讓 Blazor 應用程式加快轉譯程序。 例如,當 SetParametersAsync
中發生第一個 await
時,Blazor 元件會執行 OnInitialized
和 OnInitializedAsync
方法。 當等候的陳述式完成時,SetParametersAsync
中的執行緒會繼續。
相同的邏輯適用於整個生命週期方法系列。 同時,在 await
和 OnInitializedAsync
期間發生的每個 OnParametersSetAsync
作業都表示元件的狀態已變更,並且可觸發頁面的立即轉譯。 初始化完成之前,頁面可能會轉譯數次。
了解生命週期方法
每個元件生命週期方法都有特定的用途,且您可以覆寫方法,以將自訂邏輯新增至您的元件。 下表以發生順序列出生命週期方法,並描述其用途。
順序 | 生命週期方法 | 描述 |
---|---|---|
1 | 元件已建立 | 元件已具現化。 |
2 | SetParametersAsync | 從轉譯樹狀目錄中元件的父系設定參數。 |
3 | OnInitialized / OnInitializedAsync | 元件準備好啟動時發生。 |
4 | OnParametersSet / OnParametersSetAsync | 發生於元件收到參數和屬性指派時。 |
5 | OnAfterRender / OnAfterRenderAsync | 發生於元件轉譯之後。 |
6 | Dispose / DisposeAsync |
如果元件實作 IDisposable 或 IAsyncDisposable,就會隨著終結元件發生適當的可處置項目。 |
SetParametersAsync 方法
當使用者瀏覽包含 Blazor 元件的頁面時,Blazor 執行階段會建立新的元件執行個體,並執行預設建構函式。 建構元件之後,Blazor 執行階段會呼叫 SetParametersAsync
方法。
如果元件定義了任何參數,Blazor 執行階段會將這些參數的值從呼叫環境插入元件中。 這些參數包含在 ParameterView
物件中,並已設定為可供 SetParametersAsync
方法存取。 您可以呼叫 base.SetParametersAsync
方法,以使用這些值填入元件的 Parameter
屬性。
或者,如果您需要以不同的方式處理參數,可以使用此方法執行。 例如,在使用任何傳遞至元件的參數之前,您可能需要先加以驗證。
注意
建立元件時一律會執行 SetParametersAsync
方法,即使元件沒有任何參數亦然。
OnInitialized 和 OnInitializedAsync 方法
您可以覆寫 OnInitialized
和 OnInitializedAsync
方法來包含自訂功能。 這些方法會在 SetParametersAsync
方法填入元件的參數型屬性之後執行,其會以 ParameterAttribute 或 CascadingParameterAttribute 屬性化。 您可以在這些方法中執行初始化邏輯。
如果應用程式的 render-mode
屬性設定為 Server
,則 OnInitialized
和 OnInitializedAsync
方法只會針對一個元件執行個體執行一次。 如果元件的父系修改了元件參數,SetParametersAsync
方法將會再次執行,但這些方法則不會。 如果您需要在參數變更時重新初始化元件,請使用 SetParametersAsync
方法。 如果您想要執行初始化一次,請使用這些方法。
如果 render-mode
屬性設定為 ServerPrerendered,則 OnInitialized
和 OnInitializedAsync
方法會執行兩次;一次是在產生靜態頁面輸出的預先轉譯階段,另一次則是在伺服器建立與瀏覽器的 SignalR 連線時。 您可以在這些方法中執行昂貴的初始化工作,例如,從您用來設定 Blazor 元件狀態的 Web 服務擷取資料。 在此情況下,快取第一次執行期間的狀態資訊,並在第二次執行期間重複使用儲存的狀態。
Blazor 元件所使用的任何相依性,都會在執行個體建立之後、OnInitialized
或 OnInitializedAsync
方法執行之前插入。 您可以在 OnInitialized
或 OnInitializedAsync
方法中使用這些相依性所插入的物件,但不可在之前使用。
重要
Blazor 元件不支援建構函式相依性插入。 請改用元件標記中的 @inject
指示詞,或在屬性宣告上使用 InjectAttribute。
在預先轉譯階段期間,Blazor Server 元件中的程式碼無法執行需要連線至瀏覽器的動作,例如呼叫 JavaScript 程式碼。 您應該在 OnAfterRender
或 OnAfterRenderAsync
方法中放置相依於瀏覽器連線的邏輯。
OnParametersSet 和 OnParametersSetAsync 方法
OnParametersSet
和 OnParametersSetAsync
方法會在元件第一次轉譯時於 OnInitialized
或 OnInitializedAsync
方法之後執行,或在後續轉譯中於 SetParametersAsync
之後執行。 如同 SetParametersAsync
,即使元件沒有參數,也一律會呼叫這些方法。
使用任一方法可完成相依於元件參數值的初始化工作,例如為計算屬性計算值。 請勿在建構函式中執行這類長時間執行的作業。 建構函式是同步的,等候長時間執行的作業完成,將影響到包含元件之頁面的回應能力。
OnAfterRender 和 OnAfterRenderAsync 方法
每當 Blazor 執行階段需要更新使用者介面中的元件所表示的檢視時,OnAfterRender
和 OnAfterRenderAsync
方法就會執行。 此狀態會在下列情況時自動發生:
- 元件的狀態會變更,例如,當
OnInitialized
或OnInitializedAsync
方法或OnParametersSet
和OnParametersSetAsync
方法執行時。 - 觸發 UI 事件。
- 應用程式碼呼叫元件的
StateHasChanged
方法。
從外部事件或 UI 觸發呼叫 StateHasChanged 時,元件會有條件地重新轉譯。 下列清單詳細說明方法呼叫的順序,包括下列 StateHasChanged
:
- StateHasChanged:元件標示為需要重新轉譯。
- ShouldRender:傳回旗標,指出是否應該轉譯元件。
- BuildRenderTree:轉譯元件。
StateHasChanged
方法會呼叫元件的 ShouldRender
方法。 此方法的目的是要判斷狀態變更是否需要元件重新轉譯檢視。 根據預設,所有狀態變更都會觸發轉譯作業,但您可以覆寫 ShouldRender
方法,並定義您的決策制定邏輯。 如果應再次轉譯檢視,則 ShouldRender
方法會傳回 true
,否則會傳回 false
。
如果元件需要轉譯,則您可以使用 BuildRenderTree
方法來產生模型,用以更新瀏覽器用來顯示 UI 的 DOM 版本。 您可以使用 ComponentBase
類別提供的預設實作,或者,如果您有特定需求,可以使用自訂邏輯加以覆寫。
接著會轉譯元件檢視,並更新 UI。 最後,元件會執行 OnAfterRender
和 OnAfterRenderAsync
方法。 此時,UI 可以完整運作,而且您可以與 JavaScript 和 DOM 中的任何元素互動。 使用這些方法,執行任何其他需要存取完整轉譯內容的步驟,例如從 JS Interop 呼叫 JavaScript 程式碼。
OnAfterRender
和 OnAfterRenderAsync
方法會取得名為 firstRender
的布林值參數。 這些方法第一次執行時,此參數為 true
,但之後則為 false
。 如果在每次轉譯元件時重複執行可能造成浪費且太資源密集,您可以評估此參數以執行一次性作業。
注意
請勿將預先轉譯與 Blazor 元件的第一個轉譯搞混了。 預先轉譯會在與瀏覽器建立 SignalR 連線之前發生,並產生靜態版本頁面。 第一個轉譯會在與瀏覽器的連線完全作用,且所有功能都可供使用時發生。
Dispose 和 DisposeAsync 方法
如同任何 .NET 類別,Blazor 元件也可以使用受控和非受控資源。 執行階段會自動回收受控資源。 不過,您應該實作 IDisposable
或 IAsyncDisposable
介面,並提供 Dispose
或 DisposeAsync
方法來釋放任何非受控資源。 此作法可降低伺服器中發生記憶體流失的機率。
處理生命週期方法中的例外狀況
如果 Blazor 元件的生命週期方法失敗,其會關閉與瀏覽器的 SignalR 連線,導致 Blazor 應用程式停止運作。 若要避免此結果,請確定您已準備好隨著生命週期方法的邏輯處理例外狀況。 如需詳細資訊,請參閱處理 ASP.NET Core Blazor 應用程式中的錯誤。