前言

在前幾個章節中,我們實作了一些元件,但是元件我們不知道元件是什麼時候建立的也還不知道什麼時候會消失,今天就來說說元件從建立到銷毀的流程與事件

流程

  1. Constructor
  2. SetParametersAsync
  3. OnInitialized & OnInitializedAsync
  4. OnParametersSet & OnParametersSetAsync
  5. OnAfterRender & OnAfterRenderAsync
  6. Dispose

在Blazor元件中Constructor的用途不大,因為目前不支援建構式注入

建立一個 Lifecycle.razor 來觀察生命週期

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
@inject ILogger<Lifecycle> Logger

@code {
   
    public override async Task SetParametersAsync(ParameterView parameters)
    {
        Logger.LogInformation("SetParametersAsync-開始");
        await base.SetParametersAsync(parameters);
        Logger.LogInformation("SetParametersAsync-結束");
    }

    protected override void OnInitialized()
    {
        Logger.LogInformation("OnInitialized-開始");
        base.OnInitialized();
        Logger.LogInformation("OnInitialized-結束");
    }

    protected override async Task OnInitializedAsync()
    {
        Logger.LogInformation("OnInitializedAsync-開始");
        await base.OnInitializedAsync();
        Logger.LogInformation("OnInitializedAsync-結束");
    }

    protected override void OnParametersSet()
    {
        Logger.LogInformation("OnParametersSet-開始");
        base.OnParametersSet();
        Logger.LogInformation("OnParametersSet-結束");
    }

    protected override async Task OnParametersSetAsync()
    {
        Logger.LogInformation("OnParametersSetAsync-開始");
        await base.OnParametersSetAsync();
        Logger.LogInformation("OnParametersSetAsync-結束");
    }

    protected override void OnAfterRender(bool firstRender)
    {
        Logger.LogInformation($"OnAfterRender({firstRender})-開始");
        base.OnAfterRender(firstRender);
        Logger.LogInformation($"OnAfterRender({firstRender})-結束");
    }

    protected override async Task OnAfterRenderAsync(bool firstRender)
    {
        Logger.LogInformation($"OnAfterRenderAsync({firstRender})-開始");
        await base.OnAfterRenderAsync(firstRender);
        Logger.LogInformation($"OnAfterRenderAsync({firstRender})-結束");
    }

    public void Dispose()
    {
        Logger.LogInformation("Dispose");
    }

}

Lifecycle 在Console顯示的Log

OnInitialized & OnInitializedAsync

1
2
protected virtual void OnInitialized ();
protected virtual System.Threading.Tasks.Task OnInitializedAsync ();

這是元件初始化的執行的第一個方法

  • 於元件的 SetParametersAsync 完成後呼叫
  • 首先會呼叫同步的 OnInitialized 然後才呼叫 OnInitializedAsync
  • 資料的載入可以放在這一個步驟處理
  • 所有需要在元件渲染完成後執行重新渲染的非同步行為都應該放在OnInitializedAsync
  • OnInitializedAsync 在預先渲染時會被呼叫兩次
    • 元件以靜態的呈現時
    • 瀏覽器重新渲染時

這邊指的預先渲染是為了SEO所做的處理,因為SPA對搜尋引擎來說是一張白紙,採用預先選染可以處理SEO不佳的問題,關於 Blazor 預先渲染該怎麼做,日後會再寫一篇文章來說明

OnParametersSet & OnParametersSetAsync

1
2
protected virtual void OnParametersSet ();
protected virtual System.Threading.Tasks.Task OnParametersSetAsync ();
  • OnInitialized OnInitializedAsync 之後被呼叫
  • 當父組件重新渲染或者提供新的參數後被呼叫

OnAfterRender & OnAfterRenderAsync

1
2
protected virtual void OnAfterRender (bool firstRender);
protected virtual System.Threading.Tasks.Task OnAfterRenderAsync (bool firstRender);
  • 每一次元件重新渲染時呼叫
  • OnAfterRender 的重要用途是用於 JavaScript 初始化,因為需要DOM元素載入完成
  • 參數的 firstRender 在第一次呼叫時會是 true ,這個參數可以確保初始化只有一次

StateHasChanged

1
protected void StateHasChanged ();
  • 用來通知元件狀態變更
  • 可以手動觸發UI渲染

小結

經過上面的例子,我們可以了解Blazor元件的線性生命週期,但是在真正的現實狀況中,不是那麼的標準,要注意的是非同步方法的呼叫可能會導致生命週期順序紊亂或重疊,例如OnAfterRenderAsync 可能多次被呼叫,而上一次的 OnAfterRenderAsync 尚未執行完成,在使用上需要多注意

下一個章節是元件的事件處理