インタラクティブ機能とAPI連携
AIで動的なWeb機能を構築——APIからのデータ取得、検索・フィルターインターフェース、ローディング状態のハンドリング。
プレミアムコースコンテンツ
このレッスンはプレミアムコースの一部です。Proにアップグレードすると、すべてのプレミアムコースとコンテンツを利用できます。
- すべてのプレミアムコースを利用
- 1,000以上のAIスキルテンプレート付き
- 毎週新しいコンテンツを追加
🔄 Quick Recall: 前のレッスンでは、バニラJavaScriptでインタラクティビティを追加した——DOM操作、イベントハンドリング、フォームバリデーション。次は外部データソースへの接続と真に動的な機能の構築。
APIからのデータ取得
基本的なAPI呼び出しパターン
REST APIからデータを取得するバニラJavaScriptを作成:
APIエンドポイント:[URLまたはAPIの説明]
期待されるレスポンス形式:[フィールドを記述]のオブジェクト配列のJSON
要件:
- async/awaitとfetch()を使用
- 取得中にローディングインジケーターを表示
- HTTPエラーを処理(response.okを確認)
- ネットワークエラーを処理(fetchの周りにtry-catch)
- 安全なDOMメソッドでページにデータを表示(createElement + textContent)
- 取得失敗時にユーザーフレンドリーなエラーメッセージを表示
- タイムアウトを追加(AbortControllerで10秒後にアボート)
バニラJavaScript、依存なし。
ローディング、エラー、空状態
データ駆動の機能にはハッピーパス以外の3つの状態が必要:
APIベースの機能のUI状態を管理するバニラJavaScriptを作成:
処理すべき状態:
1. ローディング:データ読み込み中にスピナー/スケルトンを表示
2. 成功:データを表示
3. エラー:フレンドリーなメッセージとリトライボタンを表示
4. 空:APIが空の配列を返した場合に「結果なし」メッセージを表示
要件:
- 状態遷移を管理する単一関数
- リトライボタンでデータを再取得
- ローディングスピナーはアクセシブル(aria-live="polite"でアナウンス)
- エラーメッセージは技術的な詳細をユーザーに晒さない
HTML構造、各状態のCSS、JavaScriptを提供。
✅ Quick Check: 「空」状態を「成功」と別に処理する理由は?
空の結果は、データ付き成功とは異なる。ユーザーが「xyzabc」で検索して結果が0件のとき、白いページを見せると壊れたように感じる。「“xyzabc"に一致する結果はありません——別の検索語をお試しください」と伝えれば、検索は動いたが何もマッチしなかったと分かる。空状態はコミュニケーションの機会だ。
検索・フィルターインターフェース
クライアントサイド検索
リアルタイム検索フィルターをバニラJavaScriptで作成:
データ:ページにカードとして表示されるオブジェクト配列
検索動作:
- ユーザー入力に合わせてフィルター(デバウンス300ms遅延)
- 複数フィールドで検索:[title, description, category]
- 大文字小文字を区別しない
- 結果件数を表示(「Y件中X件を表示」)
- 何もマッチしない場合は「結果なし」メッセージ
- リセット用のクリアボタン
要件:
- 入力ハンドラーをデバウンス(キーストロークごとにフィルターしない)
- mark要素でマッチするテキストをハイライト
- URL状態を維持(検索クエリをURLパラメータとして追加、リフレッシュ後も保持)
- アクセシブル:結果件数の変更をスクリーンリーダーにアナウンス
バニラJavaScript、依存なし。
マルチフィルターインターフェース
リスティングページのフィルターシステムを作成:
フィルタータイプ:
- カテゴリ(チェックボックス、複数選択)
- 難易度(ラジオボタン、単一選択)
- ソート(ドロップダウン:新しい順、古い順、五十音順)
要件:
- フィルターはANDロジックで結合(カテゴリ AND 難易度)
- フィルター状態をURLに反映(共有可能なフィルターURL)
- アクティブフィルター数を表示(「フィルター3件適用中」)
- 「すべてクリア」ボタン
- アイテムの表示/非表示にスムーズトランジション
- 各オプションの利用可能アイテム数を更新
バニラJavaScript、依存なし。
一般的なインタラクティブコンポーネントの構築
タブ
アクセシブルなタブコンポーネントをバニラJavaScriptで作成:
要件:
- タブリストにrole="tablist"
- タブボタンにrole="tab"、aria-selected、aria-controls
- タブパネルにrole="tabpanel"、aria-labelledby
- キーボードナビゲーション:矢印キーでタブ間移動、Enter/Spaceで選択
- 選択されたタブパネルのみ表示
- 動的タブコンテンツのサポート(タブ切り替え時にロード)
WAI-ARIA Tabsパターンに準拠。バニラJavaScript、依存なし。
モーダル/ダイアログ
アクセシブルなモーダルダイアログをバニラJavaScriptで作成:
要件:
- トリガーボタンクリックで開く
- モーダル内にフォーカスをトラップ(Tabはモーダル要素のみを巡回)
- Escapeキー、オーバーレイクリック、閉じるボタンで閉じる
- 閉じたらトリガーボタンにフォーカスを戻す
- role="dialog"とaria-modal="true"を使用
- 開いている間は背景のスクロールを抑止
- CSSでスムーズな開閉アニメーション
WAI-ARIA Dialogパターンに準拠。バニラJavaScript、依存なし。
✅ Quick Check: モーダルでフォーカストラップが重要な理由は?
フォーカストラップなしでは、キーボードユーザーがモーダル内でTabを押すと、いずれモーダルの裏にある見えないページ要素にフォーカスが当たる。見えないボタンやリンクを操作してしまい、意図しないフォーム送信もあり得る。混乱するし危険だ。フォーカストラップにより、キーボードユーザーは意図的に閉じるまでモーダル内に留まる。
演習:動的機能を構築
- 検索・フィルターインターフェースを作成(12個以上のアイテム)
- 無料パブリックAPI(例:JSONPlaceholder)からデータを取得し、ローディングとエラー状態を実装
- コンテンツ整理用のアクセシブルなタブコンポーネントを構築
- すべての機能がキーボードのみで操作できることを確認
- 間違ったAPI URLを使ってエラー状態をテスト
Key Takeaways
- async/awaitでAPI呼び出しを読みやすくデバッグしやすくする——ネストした.then()チェーンより優先
- すべてのAPI呼び出しに3つの状態が必要:ローディング(スピナー)、エラー(フレンドリーメッセージ+リトライ)、空(役立つガイダンス)
- 秘密のAPIキーをクライアントサイドコードに置かない——認証済みAPI呼び出しにはサーバーサイドプロキシを使う
- 検索入力はデバウンス(300ms遅延)してキーストロークごとのフィルターを避け、パフォーマンスを保つ
- インタラクティブコンポーネント(タブ、モーダル、アコーディオン)はキーボードとスクリーンリーダーのアクセシビリティのためWAI-ARIAパターンに従う
- フィルター/検索状態をURLに反映し、ユーザーが特定のビューを共有・ブックマークできるようにする
Up Next: 次のレッスンでは、デバッグとパフォーマンス最適化——バグを素早く見つけ、サイトを高速に読み込ませる方法を学ぶ。
理解度チェック
まず上のクイズを完了してください
レッスン完了!