Blazor コンポーネント ライフサイクルを理解する

完了

Blazor コンポーネントには明確に定義されたライフサイクルがあります。それは最初に作成されたときに始まり、破棄されたときに終了します。 コンポーネントのライフサイクルは、特定のトリガーに応答して発生する一連のイベントによって管理されます。 このようなトリガーには、コンポーネントの初期化、ユーザーとコンポーネントの対話、コンポーネントが存在するページの終了などが含まれます。

このユニットでは、Blazor コンポーネントのライフサイクル中に発生するイベントについて学習します。 これらのイベントを処理して、行われる作業を最適化し、Blazor ページの応答性を向上させる方法を確認します。

Blazor コンポーネント ライフサイクル

Blazor コンポーネントは Blazor アプリのビューを表し、これによりレイアウトと UI ロジックが定義されます。 コンポーネントによって、アプリの実行時に HTML マークアップが生成されます。 ユーザーとの対話イベントによってカスタム コードをトリガーでき、コンポーネントを更新して表示を再レンダリングできます。 ページを閉じると、Blazor によってコンポーネントが削除され、すべてのリソースがクリーンアップされます。 ユーザーがページに戻ると、新しいインスタンスが作成されます。

次の図は、コンポーネントの有効期間中に発生するイベントと、これらのイベントを処理するために使用できるメソッドを示しています。 SetParametersAsync を除き、Blazor には、各メソッドの同期および非同期の両方のバージョンが用意されています。

すべての Blazor コンポーネントは、示されているメソッドを定義し、既定の動作を提供する、ComponentBase クラスまたは IComponent から派生します。 イベントは、対応するメソッドをオーバーライドすることによって処理します。

The Blazor component lifecycle.

この図は、ライフサイクル メソッド間にシングルスレッド フローが存在することを示していますが、これらのメソッドの非同期バージョンを使用すると Blazor アプリでレンダリング プロセスを迅速化できます。 たとえば、SetParametersAsync で最初の await が発生したとき、Blazor コンポーネントで OnInitialized および OnInitializedAsync メソッドが実行されます。 待機中のステートメントが完了すると、SetParametersAsync 内の実行スレッドが再開されます。

この同じロジックが、一連のライフサイクル メソッドの全体にわたって適用されます。 また、OnInitializedAsyncOnParametersSetAsync の処理中に発生する各 await 操作は、そのコンポーネントの状態が変更されたことを示しており、ページの即時レンダリングをトリガーできます。 初期化が完全に完了する前に、ページが複数回レンダリングされる可能性があります。

ライフサイクル メソッドを理解する

コンポーネント ライフサイクルの各メソッドには特定の目的があり、メソッドをオーバーライドしてコンポーネントにカスタム ロジックを追加できます。 次の表では、ライフサイクル メソッドを発生する順に一覧表示し、その目的について説明しています。

注文 ライフサイクル メソッド 説明
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 メソッドからアクセスできるようになります。 これらの値をコンポーネントの Parameter プロパティに入力するには、base.SetParametersAsync メソッドを呼び出します。

または、これらのパラメーターを別の方法で処理する必要がある場合は、このメソッドでそれを行います。 たとえば、コンポーネントに渡されたすべてのパラメーターの使用前の検証が必要になることがあります。

Note

SetParametersAsync メソッドは、コンポーネントにパラメーターがない場合でも、そのコンポーネントが作成されたときに常に実行されます。

OnInitialized および OnInitializedAsync メソッド

OnInitialized および OnInitializedAsync メソッドをオーバーライドして、カスタム機能を追加することができます。 これらは、SetParametersAsync メソッドによってコンポーネントのパラメーターベースのプロパティ (ParameterAttribute または CascadingParameterAttribute の属性が設定されている) が設定された後に実行されます。 これらのメソッドで初期化ロジックを実行します。

アプリケーションの render-mode プロパティが Server に設定されている場合、OnInitialized および OnInitializedAsync メソッドはコンポーネント インスタンスに対して一度だけ実行されます。 コンポーネント パラメーターがそのコンポーネントの親によって変更された場合、SetParametersAsync メソッドはもう一度実行されますが、これらのメソッドは実行されません。 パラメーターが変更されたときにコンポーネントを再初期化する必要がある場合は、SetParametersAsync メソッドを使用します。 初期化を 1 回実行したい場合は、これらのメソッドを使用します。

render-mode プロパティが ServerPrerendered に設定されている場合、OnInitialized および OnInitializedAsync メソッドは 2 回実行されます。静的なページ出力を生成するプリレンダリング フェーズ中に 1 回と、サーバーでブラウザーとの SignalR 接続が確立されたときにもう 1 回です。 これらのメソッドでは、Blazor コンポーネントの状態を設定するために使用するデータを Web サービスから取得するなど、コストのかかる初期化タスクを実行する場合があります。 この場合は、最初の実行中に状態情報をキャッシュし、保存された状態を 2 回目の実行中に再利用します。

Blazor コンポーネントによって使用される依存関係はすべて、このインスタンスが作成されたとき、OnInitialized または OnInitializedAsync メソッドが実行される前に挿入されます。 これらの依存関係によって挿入されたオブジェクトは OnInitialized または OnInitializedAsync メソッドで使用できますが、その前には使用できません。

重要

Blazor コンポーネントでは、コンストラクターの依存関係の挿入がサポートされていません。 代わりに、コンポーネント マークアップで @inject ディレクティブを使用するか、プロパティ宣言で InjectAttribute を使用します。

プリレンダリング フェーズ中に、Blazor Server コンポーネント内のコードで、ブラウザーへの接続が必要なアクション (JavaScript コードの呼び出しなど) を実行することはできません。 ブラウザーとの接続に依存するロジックは、OnAfterRender または OnAfterRenderAsync メソッドに配置する必要があります。

OnParametersSet および OnParametersSetAsync メソッド

OnParametersSet および OnParametersSetAsync メソッドは、コンポーネントが初めてレンダリングされる場合は OnInitialized メソッドまたは OnInitializedAsync メソッドの後に、それ以降にレンダリングされる場合は SetParametersAsync メソッドの後に実行されます。 SetParametersAsync と同様に、これらのメソッドは、コンポーネントにパラメーターがない場合でも常に呼び出されます。

いずれかのメソッドを使用して、コンポーネント パラメーター値に依存する初期化タスク (計算されるプロパティの値の計算など) を完了します。 コンストラクターでは、このような実行時間の長い操作を行わないでください。 コンストラクターは同期的であるため、実行時間の長い操作の完了を待っていると、そのコンポーネントを含むページの応答性に影響を与えます。

OnAfterRender および OnAfterRenderAsync メソッド

OnAfterRender メソッドと OnAfterRenderAsync メソッドは、Blazor ランタイムで、ユーザー インターフェイスのコンポーネントによって表されるビューの更新が必要になるたびに実行されます。 この状態は、次の場合に自動的に発生します。

  • コンポーネントの状態が変化する (たとえば、OnInitialized または OnInitializedAsync メソッドあるいは OnParametersSet および OnParametersSetAsync メソッドが実行されたとき)。
  • UI イベントがトリガーされる。
  • アプリケーション コードでこのコンポーネントの StateHasChanged メソッドを呼び出す。

外部イベント、UI トリガーのいずれかから StateHasChanged が呼び出されると、コンポーネントは条件付きで再レンダリングされます。 次の一覧では、StateHasChanged とその後に続くメソッド呼び出しの順序を詳しく説明しています。

  1. StateHasChanged: コンポーネントは、再レンダリングが必要であるとマークされます。
  2. ShouldRender: コンポーネントをレンダリングする必要があるかどうかを示すフラグを返します。
  3. BuildRenderTree: コンポーネントをレンダリングします。

StateHasChanged メソッドでは、このコンポーネントの ShouldRender メソッドを呼び出します。 このメソッドの目的は、状態の変更によってコンポーネントでのビューのレンダリングが必要になったかどうかを判定することです。 既定では、すべての状態変更でレンダリング操作がトリガーされますが、ShouldRender メソッドをオーバーライドして意思決定ロジックを定義することができます。 ShouldRender メソッドは、ビューを再びレンダリングする必要がある場合は true を、それ以外の場合は false を返します。

このコンポーネントにレンダリングが必要な場合は、ブラウザーでの UI の表示に使用される DOM のバージョンを更新できるモデルを生成するために BuildRenderTree メソッドを使用できます。 ComponentBase クラスによって提供される既定のメソッド実装を使用するか、または固有の要件がある場合はカスタム ロジックでそれをオーバーライドできます。

次に、コンポーネント ビューがレンダリングされ、UI が更新されます。 最後に、このコンポーネントでは OnAfterRender および OnAfterRenderAsync メソッドを実行します。 この時点では、UI が完全に機能しており、JavaScript や DOM 内のすべての要素を操作できます。 これらのメソッドを使用して、JS 相互運用から JavaScript コードを呼び出すなどの、完全にレンダリングされたコンテンツへのアクセスを必要とするその他のすべての手順を実行します。

OnAfterRender および OnAfterRenderAsync メソッドは、firstRender という名前のブール値のパラメーターを受け取ります。 このパラメーターは、そのメソッドが初めて実行されるときは true ですが、それ以降は false です。 このパラメーターを評価すれば、コンポーネントがレンダリングされるたびに繰り返すには無駄で、リソースを消費しすぎる可能性のある 1 回限りの操作を実行できます。

Note

プリレンダリングを Blazor コンポーネントの最初のレンダリングと混同しないでください。 プリレンダリングは、ブラウザーとの SignalR 接続が確立される前に発生し、ページの静的バージョンを生成します。 最初のレンダリングは、ブラウザーとの接続が完全にアクティブであり、すべての機能が使用可能なときに発生します。

Dispose および DisposeAsync メソッド

他のすべての .NET クラスと同様に、Blazor コンポーネントではマネージド リソースとアンマネージ リソースを使用できます。 マネージド リソースは、ランタイムによって自動的に再利用されます。 しかし、アンマネージ リソースを解放するには、IDisposable または IAsyncDisposable インターフェイスを実装し、Dispose または DisposeAsync メソッドを提供する必要があります。 この方法により、サーバー内でのメモリ リークの可能性が低下します。

ライフサイクル メソッドで例外を処理する

Blazor コンポーネントのライフサイクル メソッドは、失敗するとブラウザーへの SignalR 接続を閉じ、それによって Blazor アプリの機能が停止されます。 この結果を防ぐには、ライフサイクル メソッドのロジックの一部として、例外を処理する準備をするようにしてください。 詳細については、「ASP.NET Core Blazor アプリのエラーを処理する」を参照してください。

自分の知識をチェックする

1.

これらのイベントのうち、Blazor コンポーネント ライフサイクルの一部ではないイベントはどれですか?

2.

次のイベントのうち、SetParametersAsync イベントをトリガーしないのはどれですか?