JavaScript | 1 日 120 分 × 7 日アプリ学習:検索 & ソート機能付き一覧

APP JavaScript
スポンサーリンク

7日目のゴールと今日やること

7日目のテーマは
「検索 × ソート × フィルタ一覧アプリを“中級編の完成形”としてまとめる」
ことです。

ここまで 6 日間で、あなたはすでに実務レベルの一覧アプリを作り上げています。

リアルタイム検索
昇順 / 降順ソート
複合条件フィルタ
タグフィルタ(AND / OR)
ページネーション
デバウンス
ハイライト表示
状態保存(localStorage)
データ追加・削除
状態管理の分割(filters / sortState / pagination)

7日目は、これらを 「ひとつの完成したアプリ」 として整理しながら、
map / filter / sort の“型”をあなたの中に完全に定着させる日です。


アプリ全体の構造を「3 層」で再確認する

一覧アプリは、次の 3 層で構成されています。

データ処理層(map / filter / sort / slice の世界)

  • applyKeywordFilter
  • applyAgeFilter
  • applyTagFilter
  • applySort
  • applyPagination

ここは 配列を加工するロジックだけを書く場所 です。

状態管理層(filters / sortState / pagination)

  • 検索条件
  • ソート条件
  • ページ情報

アプリの“今”を表す情報を一元管理します。

UI 層(表示とイベント)

  • renderList
  • updateSortButtons
  • イベント処理(検索、ソート、タグ、ページ移動など)

UI は「表示にだけ責任を持つ」ようにします。

この 3 層構造を理解できている時点で、
あなたはもう「ただ書く人」ではなく「設計できる人」です。


map / filter / sort を“アプリの型”として理解する

一覧アプリの処理の流れ

result = applyKeywordFilter(result);
result = applyAgeFilter(result);
result = applyTagFilter(result);
result = applySort(result);
result = applyPagination(result);
JavaScript

この流れは、どんな一覧アプリでも共通しています。

検索 → フィルタ → ソート → ページ分割 → 表示

ここに map / filter / sort / slice がすべて使われています。

深掘りポイント

  • filter は「条件を増やすほど絞り込まれる」
  • sort は「比較関数」で自由に並び替え
  • slice は「配列の一部を切り出す」
  • map は「表示用のデータ変換」に使える

これらを組み合わせるだけで、
実務レベルの一覧処理が作れます。


完成形の applyFilters を“物語として読めるコード”にする

7日目版 applyFilters(完成形)

function applyFilters() {
  let result = [...users];

  result = applyKeywordFilter(result);
  result = applyAgeFilter(result);
  result = applyTagFilter(result);
  result = applySort(result);
  result = applyPagination(result);

  renderList(result);
  updateSortButtons();
  saveState();
}
JavaScript

日本語で読むとこうなる

元データをコピーする。
キーワードで絞り込む。
年齢で絞り込む。
タグで絞り込む。
ソートする。
ページ分割する。
画面に表示する。
ソートボタンの表示を更新する。
状態を保存する。

このように、
コードがそのままストーリーとして読める
のが理想の設計です。


UI 層を“ユーザーに優しい形”に仕上げる

ハイライト表示で検索結果をわかりやすくする

function highlight(text, keyword) {
  if (!keyword) return text;

  const escaped = keyword.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
  const regex = new RegExp(escaped, "gi");

  return text.replace(regex, (match) => `<mark>${match}</mark>`);
}
JavaScript

深掘りポイント

  • 正規表現でキーワードを検索
  • <mark> タグで強調
  • 大文字小文字を無視して一致

検索結果が一気に見やすくなります。


ソート UI を“状態に応じて変わる”形にする

ソートボタンの更新

function updateSortButtons() {
  sortAge.textContent =
    sortState.key === "age"
      ? `年齢 ${sortState.order === "asc" ? "▲" : "▼"}`
      : "年齢 ▲▼";

  sortName.textContent =
    sortState.key === "name"
      ? `名前 ${sortState.order === "asc" ? "▲" : "▼"}`
      : "名前 ▲▼";
}
JavaScript

深掘りポイント

  • 現在のソート状態を UI に反映
  • ユーザーが「今どうなっているか」を理解しやすい
  • 実務でよく使う UI パターン

状態保存(localStorage)で“前回の続きから使えるアプリ”にする

保存

function saveState() {
  const json = JSON.stringify({ filters, sortState, pagination });
  localStorage.setItem("listAppState", json);
}
JavaScript

読み込み

function loadState() {
  const saved = localStorage.getItem("listAppState");
  if (!saved) return;

  const parsed = JSON.parse(saved);
  Object.assign(filters, parsed.filters);
  Object.assign(sortState, parsed.sortState);
  Object.assign(pagination, parsed.pagination);

  applyFilters();
}
JavaScript

深掘りポイント

  • JSON.stringify / JSON.parse は localStorage の基本
  • 保存するのは「UI の状態」
  • 読み込んだら applyFilters で即反映

これで「毎日使える一覧アプリ」になります。


7日目のまとめと、あなたがもう持っている力

ここまでで、一覧アプリはこういう姿になりました。

リアルタイム検索
昇順 / 降順ソート
複合条件フィルタ
タグフィルタ(AND / OR)
ページネーション
デバウンス
ハイライト表示
状態保存(localStorage)
データ追加・削除
状態管理の分割(filters / sortState / pagination)
applyFilters を小さな関数の組み合わせに整理
UI とロジックの完全分離

これらはすべて
map / filter / sort / slice
という 4 つの高階関数の組み合わせで成り立っています。

今日いちばん伝えたいのは、

「ここまで来たあなたは、もう“どんな一覧アプリでも同じ型で作れる”ところまで来ている」

ということです。

データが違うだけ。
条件が違うだけ。
UI が違うだけ。

やっていることの本質は同じです。

配列をコピーする。
filter で絞る。
sort で並べる。
slice で分割する。
map で表示用に変換する。
state に反映する。
UI に描画する。

この流れを自分の言葉で説明できるようになっていたら、
あなたはもう「配列が怖い初心者」ではありません。

ここから先は、
あなたが作りたいアプリに合わせて、
この型の上に機能を積み上げていくだけです。

タイトルとURLをコピーしました