# 機能設計書 18-onBeforeMount() / onMounted()

## 概要

本ドキュメントは、コンポーネントのDOMマウント前後に実行されるライフサイクルフック `onBeforeMount()` と `onMounted()` の機能設計書である。

### 本機能の処理概要

`onBeforeMount()` はコンポーネントのDOMへのマウント直前に実行されるフックであり、`onMounted()` はマウント完了後に実行されるフックである。Composition API用のライフサイクルフックとして、`setup()` 関数内で登録する。内部的には `createHook` ファクトリ関数と `injectHook` を通じて、コンポーネントインスタンスのフック配列にコールバックを登録する仕組みである。

**業務上の目的・背景**：コンポーネントのマウント時に初期化処理（DOM操作、外部ライブラリの初期化、イベントリスナーの登録、APIデータの取得等）を実行する仕組みを提供する。`onBeforeMount` はDOMが作成される前の準備処理に、`onMounted` はDOM要素が利用可能な状態での初期化処理に使用される。

**機能の利用シーン**：
- `onBeforeMount()`: DOM生成前の最終準備処理（ほとんど使用されない）
- `onMounted()`: DOM要素へのアクセスが必要な初期化、サードパーティライブラリの初期化、ResizeObserverやIntersectionObserverの設定、初期データ取得

**主要な処理内容**：
1. `createHook(LifecycleHooks.BEFORE_MOUNT)` / `createHook(LifecycleHooks.MOUNTED)` でフック登録関数を生成
2. `injectHook()` でコンポーネントインスタンスのフック配列にコールバックを追加
3. コールバックはエラーハンドリングラッパー（`__weh`）で包まれる
4. フック実行時はトラッキングが無効化され、currentInstanceが適切に設定される
5. `onBeforeMount` のフックは同期的に（`invokeArrayFns(bm)`）実行される
6. `onMounted` のフックはpost render effectとして（`queuePostRenderEffect(m)`）キューイングされる

**関連システム・外部連携**：レンダラー（`renderer.ts`）の `setupRenderEffect` 関数内の `componentUpdateFn` で呼び出される。

**権限による制御**：権限による制御は存在しない。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 1 | App（メイン画面） | 補助機能 | DOM初期化、テーマクラス設定、リサイズイベントリスナー登録、globalThis.store設定 |
| 3 | VersionSelect（バージョン選択） | 補助機能 | ウィンドウクリック・blurイベントリスナー登録（ドロップダウン外クリック時の閉じ処理） |

## 機能種別

ライフサイクルフック / 初期化処理

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| hook | () => any | Yes | マウント前/後に実行するコールバック関数 | - |
| target | ComponentInternalInstance \| null | No | フック登録先のコンポーネントインスタンス。デフォルトはcurrentInstance | アクティブなインスタンスがない場合はDEVで警告 |

### 入力データソース

`setup()` 関数内または Composition API 関数内で開発者が直接呼び出す。

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| 戻り値 | void | 戻り値なし |

### 出力先

コンポーネントインスタンスの内部フック配列（`instance.bm` / `instance.m`）に登録される。

## 処理フロー

### 処理シーケンス

```
1. createHook(LifecycleHooks.BEFORE_MOUNT / MOUNTED) で登録関数を生成
2. 登録関数呼び出し時:
   ├─ SSRコンポーネントセットアップ中の場合: 登録をスキップ（noops）
   └─ 通常: injectHook() を呼び出し
3. injectHook(type, hook, target, prepend):
   ├─ targetが存在しない場合: DEVで警告
   ├─ target[type] 配列を取得（なければ初期化）
   ├─ __weh ラッパーを生成（エラーハンドリング + currentInstance管理 + tracking無効化）
   └─ prepend ? hooks.unshift(wrappedHook) : hooks.push(wrappedHook)
4. レンダラーでの実行:
   ├─ bm (onBeforeMount): componentUpdateFn内で invokeArrayFns(bm) として同期実行
   └─ m (onMounted): componentUpdateFn内で queuePostRenderEffect(m, parentSuspense) としてキュー実行
```

### フローチャート

```mermaid
flowchart TD
    A[onBeforeMount/onMounted呼び出し] --> B{SSRコンポーネントセットアップ中?}
    B -->|Yes| C[登録をスキップ]
    B -->|No| D[injectHook呼び出し]
    D --> E{targetあり?}
    E -->|No| F[DEV警告]
    E -->|Yes| G[hooks配列を取得/初期化]
    G --> H[__wehラッパーを生成]
    H --> I{prepend?}
    I -->|Yes| J[hooks.unshift]
    I -->|No| K[hooks.push]

    L[componentUpdateFn実行] --> M{初回マウント?}
    M -->|Yes| N[invokeArrayFns bm 同期実行]
    N --> O[レンダリング + パッチ]
    O --> P[queuePostRenderEffect m キュー実行]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-18-01 | setup()内登録 | ライフサイクルフックはsetup()の実行中に登録する必要がある | setup()実行コンテキスト |
| BR-18-02 | SSR時のスキップ | SSRコンポーネントセットアップ中はフック登録がスキップされる | isInSSRComponentSetupがtrueの場合 |
| BR-18-03 | onBeforeMountの同期実行 | onBeforeMountフックはDOMパッチ前に同期的に実行される | componentUpdateFn内、初回マウント時 |
| BR-18-04 | onMountedの非同期キュー | onMountedフックはDOMパッチ後にqueuePostRenderEffectでキュー実行される | componentUpdateFn内、初回マウント時 |
| BR-18-05 | トラッキング無効化 | フック実行中はリアクティビティのトラッキングが無効化される | injectHookの__wehラッパー内 |
| BR-18-06 | currentInstance設定 | フック実行中はcurrentInstanceが登録時のインスタンスに設定される | injectHookの__wehラッパー内 |
| BR-18-07 | エラーハンドリング | フック内で発生したエラーはcallWithAsyncErrorHandlingで捕捉される | __wehラッパー内 |

### 計算ロジック

特に複雑な計算ロジックは存在しない。

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

該当なし。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | 警告（DEV） | アクティブなコンポーネントインスタンスがない状態での呼び出し | setup()内で呼び出す |
| - | 警告（DEV） | async setup()でawait後にフック登録 | awaitの前にフック登録を行う |
| LifecycleHooks.BEFORE_MOUNT / MOUNTED | ランタイムエラー | フック内で発生した例外 | callWithAsyncErrorHandlingで捕捉、app.config.errorHandlerで処理 |

### リトライ仕様

該当なし。

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

該当なし。

## パフォーマンス要件

- `onMounted` フックはqueuePostRenderEffectでキューイングされるため、DOMパッチ後にバッチ実行される。個別のフック実行は同期的だが、複数のフックがキュー内でまとめて処理される。
- フック内での重い同期処理はレンダリングをブロックするため避けるべき。

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

特になし。

## 備考

- `onBeforeMount` のフックはインスタンスの `bm` プロパティに格納される（LifecycleHooks.BEFORE_MOUNT = 'bm'）。
- `onMounted` のフックはインスタンスの `m` プロパティに格納される（LifecycleHooks.MOUNTED = 'm'）。
- Options APIの `beforeMount` / `mounted` と同等の機能をComposition APIで提供する。
- 同一コンポーネント内で複数回呼び出した場合、登録された順序で実行される。

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | enums.ts | `packages/runtime-core/src/enums.ts` | LifecycleHooks列挙型の定義（BEFORE_MOUNT='bm', MOUNTED='m'） |

**読解のコツ**: LifecycleHooksの略称は、コンポーネントインスタンスのプロパティ名と対応している（例: `bm` は `instance.bm` に対応）。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | apiLifecycle.ts | `packages/runtime-core/src/apiLifecycle.ts` | createHookファクトリ関数（66-79行目）、onBeforeMount/onMountedの定義（85-86行目） |
| 2-2 | apiLifecycle.ts | `packages/runtime-core/src/apiLifecycle.ts` | injectHook関数（20-64行目） |

**主要処理フロー**:
1. **66-79行目**: `createHook` はSSRチェック付きのフック登録関数を生成するファクトリ
2. **73-75行目**: `isInSSRComponentSetup` がtrueの場合、SERVER_PREFETCH以外はスキップ
3. **20-25行目**: `injectHook` はtargetインスタンスの指定型のフック配列を取得
4. **27行目**: `target[type]` 配列を取得（なければ初期化）
5. **31-45行目**: `__weh` ラッパーの生成（pauseTracking, setCurrentInstance, callWithAsyncErrorHandling, resetTracking）
6. **46-50行目**: prepend指定に応じてunshift/push

#### Step 3: レンダラーでの実行を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | renderer.ts | `packages/runtime-core/src/renderer.ts` | componentUpdateFn内のbeforeMountフック呼び出し（1332-1333行目） |
| 3-2 | renderer.ts | `packages/runtime-core/src/renderer.ts` | componentUpdateFn内のmountedフック呼び出し（1418-1420行目） |

**主要処理フロー**:
- **1330行目**: `toggleRecurse(instance, false)` でエフェクトの再帰を無効化
- **1332-1333行目**: `if (bm) { invokeArrayFns(bm) }` でbeforeMountフックを同期実行
- **1348行目**: `toggleRecurse(instance, true)` でエフェクトの再帰を再有効化
- **1396行目**: レンダリング（`renderComponentRoot`）とDOMパッチ
- **1418-1420行目**: `if (m) { queuePostRenderEffect(m, parentSuspense) }` でmountedフックをキュー
- **1462行目**: `instance.isMounted = true` でマウント完了フラグを設定

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

```
onBeforeMount(hook) / onMounted(hook)
    │
    └─ createHook(lifecycle)
           │
           └─ injectHook(lifecycle, hook, target)
                  │
                  ├─ target[type] 配列取得/初期化
                  └─ __weh ラッパー生成
                         ├─ pauseTracking()
                         ├─ setCurrentInstance(target)
                         ├─ callWithAsyncErrorHandling(hook, target, type, args)
                         ├─ reset() → unsetCurrentInstance
                         └─ resetTracking()

レンダラー componentUpdateFn (初回マウント時):
    │
    ├─ toggleRecurse(instance, false)
    ├─ invokeArrayFns(bm)          ← onBeforeMountフック実行
    ├─ toggleRecurse(instance, true)
    ├─ renderComponentRoot(instance)
    ├─ patch(null, subTree, ...)
    ├─ queuePostRenderEffect(m)    ← onMountedフックをキュー
    └─ instance.isMounted = true
```

### データフロー図

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

hookコールバック ──────▶ injectHook()              ──▶ instance.bm[] / instance.m[]
                              │
                       __wehラッパー生成
                              │
                       componentUpdateFn
                              │
                       ├─ invokeArrayFns(bm)  ──▶ フック同期実行 (beforeMount)
                       └─ queuePostRenderEffect(m) ▶ フック非同期実行 (mounted)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| apiLifecycle.ts | `packages/runtime-core/src/apiLifecycle.ts` | ソース | onBeforeMount/onMountedの定義、createHook、injectHook |
| enums.ts | `packages/runtime-core/src/enums.ts` | ソース | LifecycleHooks列挙型 |
| renderer.ts | `packages/runtime-core/src/renderer.ts` | ソース | componentUpdateFn内でのフック呼び出し |
| component.ts | `packages/runtime-core/src/component.ts` | ソース | ComponentInternalInstance、currentInstance |
| errorHandling.ts | `packages/runtime-core/src/errorHandling.ts` | ソース | callWithAsyncErrorHandling |
| scheduler.ts | `packages/runtime-core/src/scheduler.ts` | ソース | queuePostRenderEffect |
| index.ts | `packages/runtime-core/src/index.ts` | ソース | onBeforeMount/onMountedのエクスポート |
