# 機能設計書 21-onActivated() / onDeactivated()

## 概要

本ドキュメントは、Vue 3の`onActivated()`および`onDeactivated()`ライフサイクルフックの機能設計を記述する。これらは`<KeepAlive>`コンポーネントによりキャッシュされたコンポーネントの活性化・非活性化時に実行されるフックである。

### 本機能の処理概要

`onActivated()`と`onDeactivated()`は、`<KeepAlive>`コンポーネントでラップされた子コンポーネントがキャッシュから復元されたとき（活性化）、またはキャッシュに格納されたとき（非活性化）に、ユーザーが定義したコールバック関数を実行するComposition APIライフサイクルフックである。

**業務上の目的・背景**：SPAにおいて、タブ切り替えやルーティングでコンポーネントを切り替える際、状態を保持したまま非表示にし、再表示時に高速に復元したいケースが頻繁に存在する。`<KeepAlive>`でキャッシュされたコンポーネントは通常のマウント/アンマウントライフサイクルが発生しないため、キャッシュからの復元・格納のタイミングで副作用の開始/停止を制御する専用フックが必要となる。

**機能の利用シーン**：タブUIでのコンポーネント切り替え時のデータ再取得、WebSocket接続の再開/一時停止、タイマーやインターバルの開始/停止、スクロール位置の復元、アナリティクスのページビュー計測など。

**主要な処理内容**：
1. `onActivated(hook)`の呼び出しにより、フック関数を`LifecycleHooks.ACTIVATED`タイプとしてコンポーネントインスタンスに登録
2. `onDeactivated(hook)`の呼び出しにより、フック関数を`LifecycleHooks.DEACTIVATED`タイプとしてコンポーネントインスタンスに登録
3. `registerKeepAliveHook`内でデアクティベーション状態チェック用のラッパー関数（`__wdc`）を生成
4. 祖先に`<KeepAlive>`ルートが存在する場合、そのルートにもフックを注入
5. `<KeepAlive>`のactivate/deactivateメソッドにより、`queuePostRenderEffect`を通じてフックを非同期実行

**関連システム・外部連携**：`<KeepAlive>`コンポーネント（キャッシュ管理）、レンダラー（activate/deactivate処理の呼び出し）、スケジューラ（`queuePostRenderEffect`によるフック実行タイミング制御）と連携する。

**権限による制御**：権限による制御は存在しない。Composition APIのsetup()関数内でのみ使用可能という制約がある。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | - | - | 画面機能マッピングに直接の関連画面なし。`<KeepAlive>`でラップされた任意のコンポーネントで使用される |

## 機能種別

ライフサイクルフック登録 / コールバック管理

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| hook | Function | Yes | 活性化/非活性化時に実行されるコールバック関数 | なし |
| target | ComponentInternalInstance \| null | No | フックを登録する対象コンポーネントインスタンス（省略時はcurrentInstance） | なし |

### 入力データソース

Composition APIのsetup()関数内からのプログラム呼び出し。

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| void | void | 戻り値なし。副作用としてコンポーネントインスタンスにフック関数を登録する |

### 出力先

コンポーネントインスタンス内部の`a`（activated hooks配列）または`da`（deactivated hooks配列）プロパティ。

## 処理フロー

### 処理シーケンス

```
1. onActivated(hook) / onDeactivated(hook) 呼び出し
   └─ registerKeepAliveHook(hook, type, target) を呼び出し
2. registerKeepAliveHook内でデアクティベーションチェックラッパー(__wdc)を生成
   └─ ラッパーは祖先チェーンを辿りisDeactivatedフラグを確認
3. injectHook(type, wrappedHook, target) でコンポーネントにフック登録
   └─ エラーハンドリングラッパー(__weh)を生成してhooks配列にpush
4. 祖先チェーンを辿り、KeepAliveルートが見つかった場合
   └─ injectToKeepAliveRoot でKeepAliveルートにもフックを注入
5. KeepAliveのactivate/deactivate実行時
   └─ queuePostRenderEffect経由でフック配列をinvokeArrayFnsで実行
```

### フローチャート

```mermaid
flowchart TD
    A[onActivated/onDeactivated呼び出し] --> B[registerKeepAliveHook]
    B --> C{__wdcラッパー既存?}
    C -->|Yes| D[既存ラッパーを使用]
    C -->|No| E[デアクティベーションチェックラッパー生成]
    D --> F[injectHook でフック登録]
    E --> F
    F --> G{targetが存在?}
    G -->|Yes| H[祖先チェーンを走査]
    G -->|No| I[終了]
    H --> J{祖先にKeepAliveルートあり?}
    J -->|Yes| K[injectToKeepAliveRoot]
    J -->|No| I
    K --> I
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-21-01 | デアクティベーションチェック | フック実行時、対象インスタンスの祖先チェーンにisDeactivated=trueのコンポーネントがある場合はフックを実行しない | onActivatedフック実行時 |
| BR-21-02 | KeepAliveルート注入 | 祖先にKeepAliveルートが存在する場合、そのルートにもフックを注入する | onActivated/onDeactivated登録時 |
| BR-21-03 | SSR時無効 | SSRコンポーネントセットアップ中はフック登録をスキップしない（KeepAlive専用のため通常のcreateHookとは異なる） | SSR時 |
| BR-21-04 | ポストレンダリング実行 | フックはqueuePostRenderEffectにより、DOMレンダリング完了後に実行される | activate/deactivate時 |

### 計算ロジック

該当なし。

## データベース操作仕様

### 操作別データベース影響一覧

該当なし（クライアントサイドフレームワーク機能）。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | 開発警告 | setup()関数外でonActivated/onDeactivatedを呼び出した場合 | injectHook内でactiveなコンポーネントインスタンスが存在しない旨の警告を出力 |
| ACTIVATED / DEACTIVATED | ランタイムエラー | フック関数内で例外が発生した場合 | callWithAsyncErrorHandlingによりエラーをキャッチし、handleErrorで処理 |

### リトライ仕様

リトライ機構は存在しない。

## トランザクション仕様

該当なし。

## パフォーマンス要件

- `__wdc`ラッパーのキャッシュにより、同一フックの重複登録を回避しスケジューラによる重複排除を可能にする
- 祖先チェーンの走査はコンポーネントツリーの深さに比例するが、KeepAliveのネストは通常浅いため実用上の問題はない

## セキュリティ考慮事項

該当なし。フレームワーク内部のライフサイクル管理機能であり、外部入力を直接扱わない。

## 備考

- `onActivated`は`LifecycleHooks.ACTIVATED`（内部キー: `'a'`）に対応
- `onDeactivated`は`LifecycleHooks.DEACTIVATED`（内部キー: `'da'`）に対応
- `<KeepAlive>`コンポーネント内でのみ意味を持ち、`<KeepAlive>`外で使用した場合はフックが呼ばれない

---

## コードリーディングガイド

本機能を理解するために参照すべきファイルと、推奨する読み解き順序を以下に示す。

### 推奨読解順序

#### Step 1: データ構造を理解する

ライフサイクルフックの種別を定義するenumを確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | enums.ts | `packages/runtime-core/src/enums.ts` | `LifecycleHooks`列挙型。`ACTIVATED = 'a'`と`DEACTIVATED = 'da'`がフックの内部キー |

**読解のコツ**: `LifecycleHooks`の値（`'a'`, `'da'`など）はコンポーネントインスタンスのプロパティ名に直接対応している。`instance.a`がactivatedフック配列、`instance.da`がdeactivatedフック配列を指す。

#### Step 2: エントリーポイントを理解する

`onActivated`/`onDeactivated`関数の定義を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | KeepAlive.ts | `packages/runtime-core/src/components/KeepAlive.ts` | `onActivated`と`onDeactivated`の実装。`registerKeepAliveHook`を呼び出す |

**主要処理フロー**:
1. **408-413行目**: `onActivated`関数。`registerKeepAliveHook(hook, LifecycleHooks.ACTIVATED, target)`を呼び出す
2. **415-420行目**: `onDeactivated`関数。`registerKeepAliveHook(hook, LifecycleHooks.DEACTIVATED, target)`を呼び出す
3. **422-458行目**: `registerKeepAliveHook`関数。`__wdc`ラッパーの生成、`injectHook`呼び出し、祖先KeepAliveルートへの注入

#### Step 3: フック登録メカニズムを理解する

`injectHook`関数でフックがコンポーネントインスタンスに登録される過程を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | apiLifecycle.ts | `packages/runtime-core/src/apiLifecycle.ts` | `injectHook`関数。エラーハンドリングラッパー`__weh`の生成と、hooks配列への追加 |

**主要処理フロー**:
- **20-64行目**: `injectHook`関数。`target[type]`配列にラッパー関数を追加する。`__weh`ラッパーはpauseTracking/resetTrackingでリアクティブ追跡を無効化し、callWithAsyncErrorHandlingでエラーハンドリングを付与

#### Step 4: フック実行メカニズムを理解する

`<KeepAlive>`コンポーネントがactivate/deactivate時にフックを呼び出す仕組みを確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | KeepAlive.ts | `packages/runtime-core/src/components/KeepAlive.ts` | `sharedContext.activate`と`sharedContext.deactivate`の実装 |

**主要処理フロー**:
- **131-167行目**: `sharedContext.activate`。DOMの移動、パッチ処理の後、`queuePostRenderEffect`内で`instance.isDeactivated = false`設定後に`invokeArrayFns(instance.a)`で全activatedフックを呼び出す
- **169-195行目**: `sharedContext.deactivate`。DOMを非表示コンテナに移動した後、`queuePostRenderEffect`内で`invokeArrayFns(instance.da)`で全deactivatedフックを呼び出し、`instance.isDeactivated = true`に設定

### プログラム呼び出し階層図

```
onActivated(hook) / onDeactivated(hook)
    │
    └─ registerKeepAliveHook(hook, type, target)
           │
           ├─ __wdc ラッパー生成（デアクティベーションチェック）
           │
           ├─ injectHook(type, wrappedHook, target)
           │      └─ __weh ラッパー生成（エラーハンドリング）
           │             ├─ pauseTracking()
           │             ├─ setCurrentInstance(target)
           │             ├─ callWithAsyncErrorHandling(hook, ...)
           │             ├─ reset()
           │             └─ resetTracking()
           │
           └─ injectToKeepAliveRoot(wrappedHook, type, target, keepAliveRoot)
                  └─ injectHook(type, hook, keepAliveRoot, true)

[実行時]
KeepAlive.activate()
    └─ queuePostRenderEffect()
           └─ invokeArrayFns(instance.a)

KeepAlive.deactivate()
    └─ queuePostRenderEffect()
           └─ invokeArrayFns(instance.da)
```

### データフロー図

```
[入力]                    [処理]                          [出力]

hook (Function)  ───▶ registerKeepAliveHook       ───▶ instance.a[] / instance.da[]
                         │                                    （フック配列に追加）
                         ├─ __wdc ラッパー生成
                         │   (isDeactivatedチェック)
                         └─ injectHook
                             └─ __weh ラッパー生成
                                 (エラーハンドリング)

[activate/deactivate時]
instance.a[] / instance.da[] ───▶ invokeArrayFns ───▶ 各フック関数実行
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| KeepAlive.ts | `packages/runtime-core/src/components/KeepAlive.ts` | ソース | onActivated/onDeactivatedの定義、registerKeepAliveHook、KeepAliveコンポーネント実装 |
| apiLifecycle.ts | `packages/runtime-core/src/apiLifecycle.ts` | ソース | injectHook関数、onActivated/onDeactivatedのre-export |
| enums.ts | `packages/runtime-core/src/enums.ts` | ソース | LifecycleHooks列挙型定義 |
| errorHandling.ts | `packages/runtime-core/src/errorHandling.ts` | ソース | callWithAsyncErrorHandling、handleError関数 |
| renderer.ts | `packages/runtime-core/src/renderer.ts` | ソース | レンダラーからKeepAliveのactivate/deactivateを呼び出す処理 |
| scheduler.ts | `packages/runtime-core/src/scheduler.ts` | ソース | queuePostRenderEffect関数（フック実行タイミング制御） |
