概要
宣言的UI(Declarative UI) は、「状態(state)」をもとにUIを再構築する設計思想であり、
命令的UI(Imperative UI) は、ユーザー操作に応じてDOMを直接操作する設計思想です。
Reactなどのモダンフレームワークは、この宣言的UIを体系化したアーキテクチャを採用しています。
(参考:React – Thinking in React)
つまり、
- 宣言的UI:状態を唯一の真実のソース(Single Source of Truth)とし、UIを「状態の関数」として再描画する。
- 命令的UI:DOMを状態として扱い、イベント発生時に逐次的に変更命令を出す。
- 両者の違いは、UIを「何から導くか」(state か DOM か)にある。
本記事では、Vanilla JSを用いてこの2つの構造を比較し、
それぞれの基本構造テンプレートと設計思想上の違いを整理します。
目次
宣言的UIの基本構造
宣言的UIとは、
「状態(state)を中心とし、UIをその写像として再描画する設計」です。
ReactやVueが採用する考え方を、Vanilla JSでも再現できます。
1. import / 初期設定セクション
2. DOM参照キャッシュ / 定数セクション
3. 関数定義セクション
│
├─ 3.1 データアクセス関数セクション(Storage I/O)
│ ├─ getState() / saveState()
│ └─ localStorageやAPI通信など
│
├─ 3.2 データ操作(ビジネスロジック)関数セクション(Model更新系)
│ ├─ addItem(), deleteItem(), updateItem()
│ └─ 状態を変更し、UI再描画関数を呼ぶ
│
├─ 3.3 イベントハンドラー関数セクション(Controller)
│ ├─ フォーム入力・ボタン押下などユーザー操作を処理
│ └─ データ操作関数を呼び出し、UI更新をトリガー
│
└─ 3.4 UI更新関数セクション(副作用を内包)
├─ 3.4.1 要素生成・属性設定
├─ 3.4.2 イベント付与
├─ 3.4.3 構造組み立て
└─ 3.4.4 DOM挿入(状態の反映)
4. 初期化 / イベントハンドラー登録セクション
特徴
- 状態(state)を単一の真実源(Single Source of Truth)として管理
-
displayBooks()などのUI更新関数が 「状態→UI再描画」 のみを担当 - イベントハンドラーは状態を更新するだけで、UIの再構築は別関数に任せる
- DOM操作は明示的命令ではなく「状態の結果」として再生成される
処理フロー(概念図)
命令的UIの基本構造(インクリメンタル型)
命令的UIとは、
「DOM自体をアプリの状態とみなし、ユーザー操作ごとに直接命令で変更する設計」です。
jQueryや古いVanilla JSコードはこの形に該当します。
1. import / 初期設定セクション
2. DOM参照キャッシュ / 定数セクション
3. 関数定義セクション
│
├─ 3.1 イベントハンドラー関数セクション(直接DOM操作)
│ ├─ onClickAdd(), onClickDelete()
│ └─ 各関数がユーザー操作に応じてUI更新関数を呼び出す
│
├─ 3.2 UI更新関数セクション(副作用を内包)
│ ├─ 3.2.1 要素生成・属性設定(createElement, setAttribute)
│ ├─ 3.2.2 イベント付与(addEventListener)
│ ├─ 3.2.3 構造組み立て(appendChildでネスト構築)
│ └─ 3.2.4 DOM挿入/削除(画面への反映・除去)
│
└─ 3.3 ユーティリティ関数セクション(任意)
├─ バリデーション、ID発行、フォーマットなどの補助処理
4. 初期化 / イベントハンドラー登録セクション
│ ├─ アプリ初期化処理(init()など)
│ └─ イベントハンドラーをDOMにバインド
特徴
- 状態(state)を別変数で保持せず、DOMがそのままアプリ状態を表す
- イベントハンドラーが
appendChild()やremoveChild()を直接実行 - UI更新は逐次的(incremental)であり、状態とUIが一体化している
- 表面上は効率的だが、状態の整合性が崩れやすく、再現性が低い
処理フロー(概念図)
宣言的UIと命令的UIを分ける構造的ポイント
| 観点 | 宣言的UI | 命令的UI |
|---|---|---|
| 状態の所在 | state / localStorage / API | DOM自身が状態を保持 |
| UI更新のトリガー | 状態変更(Model → View) | ユーザー操作(直接View更新) |
| UI更新関数の性質 | 状態をもとに再構築(全体再描画) | 一部のノードを逐次操作 |
| Controllerの責務 | Model更新のみ担当 | DOM操作を直接実行 |
| 一貫性・再現性 | 高い(stateからUIを再生成可能) | 低い(DOM依存で再現困難) |
| 代表的な例 | React, Vue, Svelte, Vanilla再描画型 | jQuery, Vanilla命令型 |
宣言的と命令的を分ける本質
両者の違いは、「UIを何から導くか」にあります。
| 概念 | 宣言的UI | 命令的UI |
|---|---|---|
| UIの生成原理 | UI = f(state) | UIを直接構築 |
| アプリの真実のソース | state(モデル層) | DOM |
| 再現可能性 | 状態があれば再構築できる | DOM操作履歴がなければ復元できない |
つまり、宣言的UIの本質は「状態とUIの分離」にあります。
この構造を採用すると、アプリの再現性・テスト容易性・保守性が飛躍的に向上します。
6. まとめ
- Vanilla JSでも、「状態を中心に再描画する構造」 を採用すれば宣言的UIを実現できる
- 命令的UIは、「UI=状態」になっているため構造がシンプルだが拡張に弱い
- 両者の違いを決めるのは 「Model層(3.1〜3.2)」の有無
- 宣言的UIの採用により、状態管理とUIロジックが明確に分離され、
React的なアーキテクチャをVanillaでも構築できる