# スクリーンとブロックのライフサイクルイベント モバイルアプリとリアクティブWebアプリにのみ適用 OutSystemsのモバイルおよびリアクティブWebアプリでは、スクリーンとブロックは一連の段階で構成されるライフサイクルに従います。これらの段階には、アプリを開いてデフォルトスクリーンに入る時、別のスクリーンに移動する時、またはスクリーンやブロックのデータを変更する時などがあります。 スクリーンまたはブロックのデータは次のとおりです: - 入力パラメータ - 変数 - 集計とデータアクション - 検証メッセージ モバイルまたはリアクティブWebアプリを実装する際、開発者はイベントハンドラアクションのセットを使用してこれらの段階に対応することができます。これらのイベントハンドラは、開発者にスクリーンとブロックのライフサイクルの可視性と、特定のイベントが発生した時にロジックを実装する機会を提供します。 イベントハンドラは、スクリーンとブロックのプロパティエディタのイベントセクション、またはデータの取得が完了した時にトリガーされるイベントハンドラの場合は、集計やデータアクションのプロパティエディタで確認および定義できます。 ## ライフサイクルの段階 ### アプリケーションを開く時 ![OutSystemsでアプリケーションを開く際のライフサイクル段階を示す図。スプラッシュスクリーンの表示、ユーザーロールの確認、データ取得イベントなどが含まれています。](https://success.outsystems.com/TK_Resource/c59e64dc-5cd6-457e-85e9-363939a19277 "アプリケーション起動時のライフサイクル") アプリケーションを開くことは、スクリーンが読み込まれる状況の一つです(もう一つの状況は別のスクリーンから移動する時です)。この場合、アプリは設定されたスプラッシュスクリーンを表示し、その後デフォルトスクリーンに移動します。 この記事ではDOMまたはDocument Object Modelについてよく言及しています。DOMについてさらに学ぶには、MDNの[DOM入門](https://developer.mozilla.org/en-US/docs/Web/API/Document_Object_Model/Introduction)をご覧ください。 スプラッシュスクリーンを表示している間、アプリケーションはユーザーロールとスクリーンへのアクセス権限を持つロール(スクリーンプロパティで定義)を照合します。この確認の後、Initializeイベントが発生し、それに対応するイベントハンドラアクション、[On Initialize](https://success.outsystems.com/ja-jp/documentation/11/building_apps/application_logic/screen_and_block_lifecycle_events/#on-initialize)がトリガーされます。このイベントが発生する時点ではデフォルトスクリーンのDOMが完全に読み込まれていないため、DOM不要なロジック(デフォルトデータの初期化など)を実装するためにこのイベントハンドラを使用できます。 On Initializeイベントハンドラが終了すると、デフォルトスクリーンの集計とデータアクションが同時にデータの取得を開始し(上の画像のGetContactsとGetProfileImagesの例)、スクリーンのDOMが読み込まれ、[Ready](https://success.outsystems.com/ja-jp/documentation/11/building_apps/application_logic/screen_and_block_lifecycle_events/#on-ready)および[Render](https://success.outsystems.com/ja-jp/documentation/11/building_apps/application_logic/screen_and_block_lifecycle_events/#on-render)イベントハンドラが実行されます。これら二つのイベントの違いは、Readyイベントはスクリーンを開く時にのみ発生するのに対し、Renderイベントはスクリーンのデータ(入力パラメータ、変数、集計とデータアクション、または検証メッセージなど)が変更されるたびにも発生することです。どちらのイベントハンドラも、読み込まれたDOMに対して動作させることができます。この時点ではデータがまだ取得されていない可能性があるため、スクリーンのデータへのアクセスは避けてください。 集計とデータアクションからのデータが取得される前でも、スクリーンは静的リソースでユーザーに表示されます。この状況を防ぐには、オフラインファーストの実装アプローチを採用してください。 スクリーンの集計とデータアクションがデータの取得を完了すると、これらのデータソースにバインドされたウィジェットは自動的に取得されたデータで更新されます。各集計とデータアクションの[After Fetch](https://success.outsystems.com/ja-jp/documentation/11/building_apps/application_logic/screen_and_block_lifecycle_events/#on-after-fetch)イベントハンドラが実行され、その後Renderイベント(スクリーンのデータが変更されたため)が続きます。各After Fetchイベントに対して、アプリケーションはRenderイベントを実行します。 ### スクリーン間の移動時 ![OutSystemsでスクリーン間を移動する際のライフサイクル段階を示すフローチャート。新しいスクリーンのDOMの読み込みと前のスクリーンの削除が強調されています。](https://success.outsystems.com/TK_Resource/8c225d3a-7279-44d1-9c9d-b913ebb736fe "スクリーン間移動のライフサイクル") あるスクリーンから別のスクリーンへの移動は、アプリケーションでよく見られるパターンです。これは通常、ボタンやリストアイテムのクリックなど、ユーザーの操作によってトリガーされます。OutSystemsでのスクリーン間の移動は、新しいスクリーンが読み込まれ、その後前のスクリーンが削除されることを意味します。 移動が開始されると、ターゲットスクリーンのDOMがすぐに読み込み始めます。これは、削除されるスクリーンのDOMとターゲットスクリーンのDOMが同時に存在することを意味します。古いスクリーンのDOMは、ターゲットスクリーンのRenderイベントの後にのみ削除され、スクリーン間の迅速でスムーズな移行を確保し、ターゲットスクリーンの読み込み段階をユーザーに表示することを避けます。 最初に実行されるイベントハンドラは[On Initialize](https://success.outsystems.com/ja-jp/documentation/11/building_apps/application_logic/screen_and_block_lifecycle_events/#on-initialize)です。アプリケーションはターゲットスクリーンのDOMの読み込みを続け、アプリケーションが開かれる時のセクションに記載されているようにイベントが続きます。これらのイベントはターゲットスクリーンに属するため、アクティブなスクリーンはターゲットスクリーンであり、DOM内の`active-screen`クラスはそのスクリーンの要素に割り当てられます。 ターゲットスクリーンの[Render](https://success.outsystems.com/ja-jp/documentation/11/building_apps/application_logic/screen_and_block_lifecycle_events/#on-render)イベントの後、スクリーン間の移行が発生し、古いスクリーンは最終的にDOMから削除されます。これは、ターゲットスクリーンのRenderイベントと古いスクリーンのDestroyイベントの間に両方のスクリーンのDOMが利用可能であることを意味します。 ### スクリーンまたはブロックのデータの変更時 スクリーンまたはブロックのデータ要素の値を変更するたびに、アプリケーションは自動的に反応します。そのため、Renderイベントがトリガーされ、データに依存するUI要素が自動的に更新されます。従来のWebアプリのように、UI要素を明示的に更新する必要はありません。 スクリーンまたはブロックの集計とデータアクションの場合、それらの新しい値はUI要素に自動的に更新されますが、クエリを明示的に再実行する必要があります。これはロジック内の[Refresh Data](https://success.outsystems.com/ja-jp/documentation/11/reference/outsystems_language/logic/implementing_logic/logic_tools/refresh_data/)フロー要素を使用して行うことができます。 データが取得された後、[After Fetch](https://success.outsystems.com/ja-jp/documentation/11/building_apps/application_logic/screen_and_block_lifecycle_events/#on-after-fetch)イベントが発生し、集計またはデータアクションから返されたデータがスクリーンまたはブロックのデータに属し変更されたため、Renderイベントも発生します。 例として、ある連絡先の詳細とその連絡先への通話リストを表示するスクリーンを想像してください。通話を取得するために、現在の連絡先識別子が割り当てられたスクリーン変数の値でフィルタリングされた集計を使用します。連絡先が変更されると、スクリーンは新しい連絡先の詳細を表示するため、スクリーン変数は新しい連絡先識別子を含むように変更されます。この新しい連絡先への通話リストを取得するには、集計を再度実行する必要があります。これを行うには、ロジック内のRefresh Dataフロー要素を呼び出し、それぞれの集計またはデータアクションを選択するだけです。クエリが新しい通話リストを返すと、スクリーン内のリストは自動的に更新されます。 ### ブロックのパラメータの変更時 ![OutSystemsでブロックのパラメータを変更する際のライフサイクルイベントを示すシーケンス図。Parameters ChangedイベントとRenderイベントが含まれています。](https://success.outsystems.com/TK_Resource/fa0bf311-5faf-4afe-887a-bd0371deec99 "ブロックパラメータ変更のライフサイクル") 入力パラメータの1つが変更された時にブロックの通知と更新を可能にするために、アプリケーションはブロックの[Parameters Changed](https://success.outsystems.com/ja-jp/documentation/11/building_apps/application_logic/screen_and_block_lifecycle_events/#on-parameters-changed)イベントハンドラを実行します。このイベントハンドラの一般的な使用例は、入力パラメータに依存する集計またはデータアクションを再実行することです。上の画像では、カレンダーの日付が変更された後、チャートの新しい値を取得するためにクエリが再度実行されています。 入力パラメータはブロックのデータの一部であるため、Parameters Changedイベントの後に[Render](https://success.outsystems.com/ja-jp/documentation/11/building_apps/application_logic/screen_and_block_lifecycle_events/#on-render)イベントもトリガーされます。 ## ライフサイクルイベントハンドラ |イベント|説明| |---|---| |[On Initialize](https://success.outsystems.com/ja-jp/documentation/11/building_apps/application_logic/screen_and_block_lifecycle_events/#on-initialize)|ユーザーのスクリーンへのアクセス権限を確認した後、スクリーンへの移動とデータの取得の前に発生します。ブロックでは、移動後に発生します。デフォルトデータを設定することでスクリーンまたはブロックを初期化するために使用できます。| |[On Ready](https://success.outsystems.com/ja-jp/documentation/11/building_apps/application_logic/screen_and_block_lifecycle_events/#on-ready)|スクリーンまたはブロックのDOMの準備が整った後、移行が開始される前に発生します。| |[On Render](https://success.outsystems.com/ja-jp/documentation/11/building_apps/application_logic/screen_and_block_lifecycle_events/#on-render)|スクリーンまたはブロックのOn Readyイベントハンドラの直後、およびスクリーンまたはブロックのデータが変更されるたびに発生します。サードパーティコンポーネントを更新するために使用できます。| |[On After Fetch](https://success.outsystems.com/ja-jp/documentation/11/building_apps/application_logic/screen_and_block_lifecycle_events/#on-after-fetch)|集計またはデータアクションがデータの取得を完了した後、このデータがスクリーンまたはブロックにレンダリングされる前に発生します。取得したデータに対して動作するために使用できます。| |[On Parameters Changed](https://success.outsystems.com/ja-jp/documentation/11/building_apps/application_logic/screen_and_block_lifecycle_events/#on-parameters-changed)|親スクリーンまたはブロックがその入力パラメータの1つを変更するたびに、ブロックで発生します。ブロック内での入力値の変更はこのイベントハンドラをトリガーしません。変数の更新などのブロックパラメータの変更に反応するために使用できます。| |[On Destroy](https://success.outsystems.com/ja-jp/documentation/11/building_apps/application_logic/screen_and_block_lifecycle_events/#on-destroy)|スクリーンまたはブロックを破棄し、DOMから削除する前に発生します。イベントリスナーの削除など、コンポーネントが破棄される時にロジックを実装するために使用できます。| ### On Initialize On Initializeイベントハンドラは、ユーザーのスクリーンへのアクセス権限を確認した後、スクリーンへの移動とデータの取得を開始する前に実行されます。 ブロックでは、このフローにサーバーアクションの呼び出しやローカルストレージの操作を含めると、このアクションが完了する前にブロックのレンダリングが開始される可能性があります。このフローでレンダリングに影響する変数を設定すると問題が発生します。 注意事項: - このイベントハンドラアクションはシンプルに保ち、ローカルストレージの操作などの遅いアクションは避けてください。スクリーンやブロックのレンダリングが遅れる可能性があります。 - このアクションはデータが取得される前に実行されるため、スクリーンやブロックのデータへのアクセスは避けてください。 このイベントハンドラで実装できるユースケース: - 入力に基づいて変数を割り当てる。 - ランダム数などのJavaScriptでの計算に基づいて変数を割り当てる。 - ユーザーがスクリーンを表示する権限を持っていない場合、アプリケーションを別のスクリーンにリダイレクトする(イベントハンドラがスクリーンに属している場合のみ可能)。 - スクリーンの入力に基づいて子ブロックのパラメータを割り当てる。 - JavaScriptのwindowオブジェクトの変数にアクセスする。 ### On Ready On Readyイベントハンドラは、スクリーンまたはブロックの準備が整った時、つまりDOMの準備が整った後、最初のレンダリングの後に実行されます。ブロックでは、このイベントは親スクリーンまたはブロックの同じイベントの前に発生します。スクリーンまたはブロックの高速でスムーズなレンダリングを確保するために、このイベントはスクリーンへの移行が終了する前にトリガーされます。 注意事項: - このイベントがトリガーされると、前のスクリーンと現在のスクリーンのDOMが読み込まれています。作成されているスクリーンで操作を確実に行うには、`active-screen`クラスを持つHTML `div`要素に対してのみロジックを実行してください。 - このイベントハンドラアクションはシンプルに保ち、並行して実行されるスクリーン集計やデータアクションを使用して、利用できない可能性のあるデータを操作することは避けてください。 - このアクションはデータが取得される前に実行されるため、スクリーンやブロックのデータへのアクセスは避けてください。これらのデータに対するロジックを開発する必要がある場合は、それぞれの集計またはデータアクションのOn After Fetchイベントハンドラを使用してください。 このイベントハンドラで実装できるユースケース: - DOMを必要とするサードパーティコンポーネントを初期化する。 - DOM要素にリスナーを追加する。 - 入力ウィジェットにフォーカスを設定する。 - JavaScriptのwindowオブジェクトにリスナーを追加する。 ### On Render On Renderイベントハンドラは、スクリーンまたはブロックがレンダリングされるたびに実行されます。つまり、スクリーンまたはブロックが開かれるたび(On Readyイベントハンドラの実行直後)、およびスクリーンのデータが変更された後に実行されます。ブロックでは、このイベントは親スクリーンまたはブロックの同じイベントの前に発生します。このイベントハンドラを使用して、プログレスバーなどのサードパーティコンポーネントを更新できます。 注意事項: - スクリーンまたはブロックのデータを変更すると、このデータが変更されるたびにOn Renderイベントが再度トリガーされ、アプリが無限ループに陥る可能性があるため、データの変更は避けてください。 - このイベントハンドラアクションはシンプルに保ち、サーバーリクエストなどの遅いアクションは避けてください。スクリーンまたはブロックのレンダリングが遅れる可能性があります。 - スクリーンまたはブロックの最初のレンダリング時には、データがすでに取得されているという保証がないため、スクリーンまたはブロックのデータへのアクセスは避けてください。これらのデータに対するロジックを開発する必要がある場合は、それぞれの集計またはデータアクションのOn After Fetchイベントハンドラを使用してください。 このイベントハンドラで実装できるユースケース: - サードパーティコンポーネントを更新するために、スクリーンまたはブロックのデータの変更に基づいて動作する。 - On Readyイベントハンドラと同じユースケース。 ### On After Fetch On After Fetchイベントハンドラは、集計またはデータアクションがデータの取得を完了した直後に実行されます。各集計またはデータアクションには独自のOn After Fetchイベントハンドラがあるため、そのデータソースから取得したデータに基づいて動作するロジックを実装できます。 注意事項: - On After Fetchイベントハンドラが実行される時、データは到着して利用可能ですが、ウィジェットにバインドされていません。つまり、ウィジェットはまだ更新されていません。 このイベントハンドラで実装できるユースケース: - クエリによって返された最初または最後のレコードを変数に割り当てる。 - マスター詳細パターンでは、リストのリストを入力するためにクエリを繰り返す。 - 他のクエリに依存するクエリの場合、このイベントハンドラを使用して依存する集計をトリガーできます。 ### On Parameters Changed On Parameters Changedは、親スクリーンまたはブロックがブロックの入力を変更した後に実行されるブロック専用のイベントハンドラです。別のブロック内にブロックがあり、外側のブロックの入力の変更がネストされたブロックの入力に影響する場合、外側のブロックのOn Parameters Changedイベントハンドラは、ネストされたブロックの同じイベントの前に実行されます。このイベントハンドラを使用して、変数の更新や集計とデータアクションの再実行など、入力パラメータの変更にブロックを適応させることができます。 このイベントハンドラで実装できるユースケース: - その入力パラメータに依存する集計またはデータアクションを更新する。 - 入力パラメータに依存する変数を再計算する。 ### On Destroy On Destroyイベントハンドラは、スクリーンまたはブロックが破棄される時に実行されます。スクリーンでは、このイベントは新しいスクリーンへの移行が終了した時に発生します。ブロックでは、このイベントはブロックがDOMから削除される前に発生します。このイベントはトップダウン順で発生します:ネストされたブロックを持つスクリーンがある場合、イベントは最初にスクリーンで発生し、次に外側のブロックで発生し、その後ネストされたブロックで発生します。このイベントハンドラを使用して、イベントリスナーの削除など、スクリーンまたはブロックの痕跡を削除するロジックを実装できます。 注意事項: - このイベントがトリガーされると、現在のスクリーンとターゲットスクリーンのDOMが読み込まれています。破棄されているスクリーンで操作を確実に行うには、`active-screen`クラスを持つHTML `div`要素に対してのみロジックを実行してください。 - このイベントハンドラアクションはシンプルに保ち、サーバーリクエストなどの遅いアクションは避けてください。スクリーンまたはブロックの削除が遅れる可能性があり、スクリーンを終了する場合は次のスクリーンの読み込みも遅れる可能性があります。 このイベントハンドラで実装できるユースケース: - サードパーティコンポーネントのdestroyアクションを呼び出す。 - プラグインを再度実行するためにDOMをクリーンアップする。 - JavaScriptリスナーを削除する。