# 機能設計書 33-v-show

## 概要

本ドキュメントは、Vue 3の組み込みディレクティブ`v-show`のランタイム実装の機能設計を記載する。`v-show`はCSS `display`プロパティの操作により要素の表示・非表示を制御するディレクティブである。

### 本機能の処理概要

`v-show`ディレクティブは、条件値に基づいてHTML要素の`display`CSSプロパティを`none`に設定することで、要素の表示・非表示を切り替える。`v-if`と異なり、要素はDOMに常に存在し続ける。

**業務上の目的・背景**：要素の表示切替は最も基本的なUI操作の1つである。`v-if`がDOMの追加/削除を行うのに対し、`v-show`はCSSのdisplayプロパティを操作するだけのため、頻繁に表示を切り替える要素に対してパフォーマンス上の利点がある。初期レンダリングコストは`v-if`より高いが、トグルコストが低いため、頻繁な切り替えに適している。

**機能の利用シーン**：タブ切替、トグルメニュー、フィルター表示、ツールチップなど、頻繁に表示状態が変わるUI要素に対して使用される。

**主要な処理内容**：
1. `beforeMount`フック: 要素の元のdisplay値を保存し、トランジション連携または直接的なdisplay設定
2. `mounted`フック: トランジションがある場合のenter処理
3. `updated`フック: 値変更時のdisplay切替（トランジション対応）
4. `beforeUnmount`フック: アンマウント前のdisplay復元
5. SSR向けの`getSSRProps`実装

**関連システム・外部連携**：`Transition`コンポーネントと連携し、表示/非表示の切替にアニメーション効果を適用できる。`BaseTransition`の`persisted`モードと組み合わせて使用される。

**権限による制御**：特になし。

## 関連画面

画面機能マッピングに該当する画面関連情報なし。

## 機能種別

条件付き表示制御 / ディレクティブ

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| value | `any` | Yes | 表示条件（truthyで表示、falsyで非表示） | - |

### 入力データソース

- テンプレート内の`v-show`バインディング式

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| el.style.display | `string` | 要素のCSS displayプロパティ |
| el[vShowHidden] | `boolean` | 要素が非表示状態かどうかのフラグ |

### 出力先

- DOM要素のstyle.displayプロパティ
- SSR時はstyleオブジェクトとして返却

## 処理フロー

### 処理シーケンス

```
1. beforeMount フック
   ├─ el[vShowOriginalDisplay]に元のdisplay値を保存
   ├─ display='none'の場合は空文字列として保存
   ├─ transitionがありvalueがtruthyなら transition.beforeEnter(el)
   └─ transitionがない場合は setDisplay(el, value)
2. mounted フック
   └─ transitionがありvalueがtruthyなら transition.enter(el)
3. updated フック
   ├─ !value === !oldValueなら処理スキップ
   ├─ transitionありの場合:
   │   ├─ value=truthy: beforeEnter → setDisplay(true) → enter
   │   └─ value=falsy: leave(→ setDisplay(false))
   └─ transitionなしの場合: setDisplay(el, value)
4. beforeUnmount フック
   └─ setDisplay(el, value) で最終状態を設定
```

### フローチャート

```mermaid
flowchart TD
    A[v-show updated] --> B{value変化あり?}
    B -->|No| C[処理スキップ]
    B -->|Yes| D{transitionあり?}
    D -->|No| E[setDisplay直接設定]
    D -->|Yes| F{value=truthy?}
    F -->|Yes| G[beforeEnter → setDisplay true → enter]
    F -->|No| H[leave → setDisplay false]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-33-01 | オリジナルdisplay保存 | 要素のオリジナルのdisplay値を`vShowOriginalDisplay`シンボルで保存 | beforeMount時 |
| BR-33-02 | display:none変換 | 元のdisplayが'none'の場合は空文字列として保存（表示時にblockなどのデフォルトに戻す） | beforeMount時、display='none'の場合 |
| BR-33-03 | 値変更スキップ | `!value === !oldValue`で真偽値として同等の場合は更新をスキップ | updated時 |
| BR-33-04 | Transition連携 | vnode.transitionが存在する場合、Transitionのenter/leaveフックを経由して表示切替 | transitionプロパティ存在時 |

### 計算ロジック

`setDisplay`関数: `el.style.display = value ? el[vShowOriginalDisplay] : 'none'`

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

該当なし。

## エラー処理

### エラーケース一覧

特にエラーケースはなし。不正な値が渡された場合もfalsyとして扱われる。

### リトライ仕様

該当なし。

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

該当なし。

## パフォーマンス要件

- DOMの追加/削除を行わず、CSSプロパティの変更のみのため、v-ifより低いトグルコスト
- `!value === !oldValue`による高速な変更検出

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

- `v-show`で非表示にした要素はDOMに残り、ブラウザの開発者ツール等から確認可能。機密情報の非表示には`v-if`を使用すべき。

## 備考

- `vShowOriginalDisplay`シンボル: `_vod` (Vue Original Display)
- `vShowHidden`シンボル: `_vsh` (Vue Show Hidden)
- `name: 'show'`プロパティはハイドレーション時のpropミスマッチチェックに使用される

---

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

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

### 推奨読解順序

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

`VShowElement`インターフェースとシンボルキーを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | vShow.ts | `packages/runtime-dom/src/directives/vShow.ts` | `VShowElement`インターフェース（6-10行目）、シンボル定義（3-4行目） |

**読解のコツ**: `vShowOriginalDisplay`と`vShowHidden`はユニークシンボルとして定義され、要素の内部状態管理に使用される。TypeScriptの`unique symbol`により型安全性が保証される。

#### Step 2: ディレクティブ本体を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | vShow.ts | `packages/runtime-dom/src/directives/vShow.ts` | `vShow`ディレクティブオブジェクト（12-48行目） |

**主要処理フロー**:
1. **15-23行目**: `beforeMount` - 元のdisplay値を保存
2. **24-28行目**: `mounted` - トランジションenter処理
3. **29-43行目**: `updated` - 値変更に応じた表示切替
4. **45-47行目**: `beforeUnmount` - 最終状態設定

#### Step 3: setDisplay関数を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | vShow.ts | `packages/runtime-dom/src/directives/vShow.ts` | `setDisplay`関数（50-53行目） |

#### Step 4: SSR対応を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | vShow.ts | `packages/runtime-dom/src/directives/vShow.ts` | `initVShowForSSR`（57-63行目） |

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

```
v-show ディレクティブ
    │
    ├─ beforeMount()
    │      └─ setDisplay(el, value) or transition.beforeEnter(el)
    │
    ├─ mounted()
    │      └─ transition.enter(el)
    │
    ├─ updated()
    │      ├─ transition.beforeEnter(el) + setDisplay(true) + transition.enter(el)
    │      ├─ transition.leave(el, () => setDisplay(false))
    │      └─ setDisplay(el, value)
    │
    └─ beforeUnmount()
           └─ setDisplay(el, value)
```

### データフロー図

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

v-show バインディング値
  (truthy/falsy) ────────▶ vShow ディレクティブ
                           ├─ 初回: 元のdisplay保存        ──▶ el[_vod] (保存)
                           ├─ transition連携判定
                           └─ setDisplay()                  ──▶ el.style.display
                                                                 ('none' or 元の値)
                                                            ──▶ el[_vsh] (状態フラグ)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| vShow.ts | `packages/runtime-dom/src/directives/vShow.ts` | ソース | v-showディレクティブのメイン実装 |
| index.ts | `packages/runtime-dom/src/index.ts` | ソース | v-showのエクスポート |
| runtimeHelpers.ts | `packages/compiler-dom/src/runtimeHelpers.ts` | ソース | コンパイラからのランタイムヘルパー参照 |
| BaseTransition.ts | `packages/runtime-core/src/components/BaseTransition.ts` | ソース | Transitionとの連携（persistedモード） |
