以下では、DOMを用いた「動的なリスト生成(Todoリストアプリ)」を題材に、実装の流れ・重要API・設計の考え方・発展要素までを体系的に解説します。最小構成のコード(HTML/CSS/JavaScript)も提示します。絵文字は使用しません。
1. ゴールと要件
-
入力フォームからタスクを追加できる
-
追加したタスクを一覧表示し、完了/未完了の切り替え、編集、削除ができる
-
表示フィルタ(すべて/未完了/完了)を切り替えられる
-
ページ再読み込み後も保持(localStorage)
-
DOM操作は「パフォーマンス」と「可読性」を意識(イベント委任、DocumentFragment など)
-
基本的なアクセシビリティ(ラベル、ロール、キーボード操作)
2. 最小実装(動くサンプル)
2.1 HTML
2.2 JavaScript(app.js)
3. 実装で押さえるDOM APIとパターン
-
要素生成と差し替え
-
document.createElement()、template要素、cloneNode(true) -
一括差し替えに
DocumentFragmentとElement.replaceChildren()を用いると、Reflow回数を抑えやすい。
-
-
イベント委任
-
ulに一度だけリスナーを付け、event.target.closest('...')で目的のボタンやチェックボックスを判定。項目数が増えてもリスナーが増えず高効率。
-
-
状態とUIの単方向反映
-
ソースオブトゥルースを JavaScript の
state.todosに集約し、render()で DOM を生成して反映。部分更新よりもバグを避けやすい。
-
-
永続化
-
localStorageで直列化し、起動時に読み出す。例ではJSON.stringify()/JSON.parse()を使用。
-
-
アクセシビリティ
-
入力に
label、リストにrole="list"、ライブ領域aria-live。ツールバー風のフィルタにaria-pressedを使用。編集はcontenteditableでキーボード確定・キャンセルを対応。
-
4. パフォーマンス上の注意
-
項目数が多い場合、描画は都度フル再描画でも
DocumentFragmentによるバッチ更新で十分高速。さらに必要なら差分パッチ(キー付きで比較)を検討。 -
スタイル計算・レイアウトの強制同期を避けるため、読みと書きを分離し、ループ内で
offsetWidthなどレイアウト情報を繰り返し参照しない。 -
入力時に連打されるイベントにはデバウンスやスロットリングを検討。
5. セキュリティ上の注意
-
ユーザー入力は
textContentを使って挿入し、innerHTMLで直接注入しない。テンプレートでもtextContentを徹底して XSS を防ぐ。 -
contenteditable使用時は貼り付けでHTMLが入らないよう、確定時に.textContentをトリムして保存。
6. テスト観点
-
追加、削除、完了切替、編集確定・キャンセル、フィルタ切替の単体テスト
-
localStorage への保存・復元テスト(モック化)
-
アクセシビリティの静的検査(role、aria-属性の有無)
7. よくある拡張
-
期日・優先度・タグ付けと並べ替え
-
一括操作(すべて完了、完了の一括削除)
-
Drag & Drop による並び替え(HTML5 DnDやPointer Events)
-
サーバ同期(REST/GraphQL)とオフライン対応(IndexedDB、Service Worker)
-
仮想スクロール(大量データ向け)
8. まとめ
動的なリスト生成は、DOMの基礎操作(生成・挿入・イベント・属性操作)を一通り実践できます。上記のサンプルは、イベント委任とフラグメントを使った効率的な再描画、localStorage による永続化、textContent による安全な描画、簡単なアクセシビリティといった実務的なベストプラクティスを含んでいます。必要に応じて拡張機能を重ねつつ、状態を一元管理して UI をレンダリングする設計を維持すると保守性が高まります。
ChatGPT5 生成日:2025/09/11