7日目のゴールと今日やること
7日目のテーマは
「ミニ総合アプリを“自分で説明できる完成作品”にする」
ことです。
ここまで 6 日間であなたは、かなり多くのことを積み上げてきました。
入力
一覧
削除
条件分岐
というキーワードからスタートして、
オブジェクト配列でのデータ管理
ID 管理
編集・完了フラグ・表示モード
バリデーション
localStorage による保存
件数の集計と状態メッセージ
まで、一通りの「ミニ Web アプリの構成要素」を体験しています。
7日目は、
アプリ全体の流れを整理して言語化する
コードを読みやすく整える(コメント・命名)
「自分なりの仕様」を一つだけ追加してみる
という、“仕上げと振り返り”の日にします。
このミニ総合アプリは何をしているアプリかを言葉にする
アプリの機能を自分の言葉で説明してみる
まずは、あなた自身の言葉でこう説明できるかを意識してみてください。
タイトルとカテゴリを入力してタスクを追加できる
一覧でタスクを確認できる
タスクを完了・未完了に切り替えられる
タスクを削除できる
表示モードを切り替えて「すべて/未完了/完了のみ」を見られる
件数の集計が表示される
ブラウザを閉じてもデータが残る
これを「人に説明できる」ようになることが、
実はコードを書くことと同じくらい大事です。
アプリ全体の構造をもう一度整理する
データ(モデル)の部分
このアプリの“心臓”は items 配列です。
一件はこういう形でした。
{
id: 1,
title: "資料作成",
category: "仕事",
done: false
}
JavaScriptここに、
タイトル(表示のメイン)
カテゴリ(分類)
完了フラグ(状態)
という「意味のある情報」がまとまっています。
さらに、
items 自体は localStorage に保存されることで、
「一時的な変数」ではなく
「アプリの状態」として扱われています。
画面(ビュー)の部分
画面側は、大きく分けて次のような領域があります。
入力欄(タイトル・カテゴリ・追加ボタン)
一覧表示エリア
エラー表示エリア
集計表示エリア
状態メッセージエリア
表示モード切り替えボタン
JavaScript は、
items の中身をもとに
この画面を「毎回描き直す」スタイルで動いています。
ロジック(制御)の部分
制御の中心は、次のような関数たちです。
addItem
updateItem(もし編集を入れていれば)
toggleDone
deleteItem
renderList
renderStats
updateStatusMessage
saveItems / loadItems
これらが、
入力イベント
ボタンクリック
ページ読み込み
といったタイミングで呼ばれ、
アプリ全体が動いています。
アプリの「1サイクル」を追ってみる
追加の流れを頭の中でトレースする
タイトルとカテゴリを入力して「追加」を押したとき、
何が起きているかを順番に追ってみます。
入力欄から値を取り出す
バリデーション関数でチェックする
問題なければ newItem オブジェクトを作る
items に push する
saveItems() で localStorage に保存する
renderList() で一覧を描き直す
renderStats() で件数を更新する
updateStatusMessage() で状態メッセージを更新する
この「流れを説明できる」ことが、
かなり大きな成長ポイントです。
完了切り替えの流れ
完了ボタンを押したときはこうです。
どのタスクかを id で特定する
対象の item を find で見つける
done フラグを反転させる
saveItems() で保存する
renderList() で見た目(取り消し線など)を更新する
renderStats() と updateStatusMessage() で集計とメッセージを更新する
ここでもやはり、
状態を変える
保存する
画面を更新する
というパターンが繰り返されています。
コードを「他人に渡せるレベル」に整える
コメントで「意図」を残す
7日目では、
コードの中に「なぜそうしているのか」を
コメントとして残していきます。
例として、重要な部分だけコメント付きで書いてみます。
// タスク一覧を保持する配列(アプリのメインデータ)
const items = [];
let nextId = 1; // 次に使う ID
let viewMode = "all"; // 表示モード: all | todo | done
const STORAGE_KEY = "miniAppItems"; // localStorage 用キー
// データをブラウザに保存する
function saveItems() {
const json = JSON.stringify(items); // 配列を JSON 文字列に変換
localStorage.setItem(STORAGE_KEY, json);
}
// ブラウザからデータを読み込む
function loadItems() {
const json = localStorage.getItem(STORAGE_KEY);
if (!json) return;
try {
const data = JSON.parse(json); // JSON 文字列を配列に戻す
if (Array.isArray(data)) {
items.length = 0;
data.forEach((item) => items.push(item));
// nextId を復元(最大の id + 1 にしておく)
const maxId = items.reduce((max, item) => Math.max(max, item.id), 0);
nextId = maxId + 1;
}
} catch (e) {
console.error("保存データの読み込みに失敗しました", e);
}
}
// 新しいタスクを追加する
function addItem(title, category) {
const newItem = {
id: nextId,
title,
category,
done: false
};
items.push(newItem);
nextId += 1;
saveItems();
}
// 完了フラグを切り替える
function toggleDone(id) {
const target = items.find((item) => item.id === id);
if (!target) return;
target.done = !target.done;
saveItems();
}
// タスクを削除する
function deleteItem(id) {
const newItems = items.filter((item) => item.id !== id);
items.length = 0;
newItems.forEach((i) => items.push(i));
saveItems();
}
// 集計情報を計算する
function getStats() {
const total = items.length;
const doneCount = items.filter((item) => item.done).length;
const todoCount = total - doneCount;
return { total, doneCount, todoCount };
}
JavaScriptこうやってコメントを付けていくと、
「自分が何をしているのか」がよりクリアになります。
自分なりの仕様を一つだけ足してみる
例として「カテゴリごとの色分け」を足す
せっかくなので、
7日目の仕上げとして「自分のアイデア」を一つだけ足してみましょう。
例えば、カテゴリごとに色を変える、というのはどうでしょう。
仕事 → 青系
プライベート → 緑系
その他 → グレー
renderList の中で、カテゴリに応じて色を変えられます。
function getCategoryColor(category) {
if (category === "仕事") return "#1e90ff";
if (category === "プライベート") return "#228b22";
return "#555555";
}
function renderList() {
listArea.innerHTML = "";
let visibleItems = items;
if (viewMode === "todo") {
visibleItems = items.filter((item) => !item.done);
} else if (viewMode === "done") {
visibleItems = items.filter((item) => item.done);
}
if (visibleItems.length === 0) {
const p = document.createElement("p");
p.textContent = "表示できるデータがありません。";
listArea.appendChild(p);
return;
}
visibleItems.forEach((item) => {
const row = document.createElement("div");
const titleSpan = document.createElement("span");
titleSpan.textContent = item.title;
if (item.done) {
titleSpan.style.textDecoration = "line-through";
titleSpan.style.color = "#888";
}
const categorySpan = document.createElement("span");
categorySpan.textContent = `(${item.category})`;
categorySpan.style.marginLeft = "8px";
categorySpan.style.color = getCategoryColor(item.category);
const doneButton = document.createElement("button");
doneButton.textContent = item.done ? "未完了に戻す" : "完了";
doneButton.addEventListener("click", () => {
toggleDone(item.id);
renderList();
renderStats();
updateStatusMessage();
});
const deleteButton = document.createElement("button");
deleteButton.textContent = "削除";
deleteButton.addEventListener("click", () => {
deleteItem(item.id);
renderList();
renderStats();
updateStatusMessage();
});
row.appendChild(titleSpan);
row.appendChild(categorySpan);
row.appendChild(doneButton);
row.appendChild(deleteButton);
listArea.appendChild(row);
});
}
JavaScriptこういう「自分の好み」を一つ入れるだけで、
それはもう「教材のコード」ではなく
あなたの作品になります。
7日間を通して、あなたが身につけたこと
ここまでの 7 日間で、あなたは確実にこういう力を身につけています。
配列とオブジェクトでデータを設計する力
DOM を使って画面を組み立てる力
イベント(クリック・入力)をトリガーに動きを作る力
条件分岐で「状態に応じた振る舞い」を決める力
localStorage で状態を保存・復元する力
コードを整理し、コメントで意図を残す力
そして何より、
「入力・一覧・削除・条件分岐」という
一見バラバラな要素が、
一つのアプリとしてつながる感覚
を、ちゃんと体で掴んでいます。
ここから先は、
このミニ総合アプリをベースにして、
入力項目を増やす
デザインを整える
別の種類のアプリに作り変えてみる
など、いくらでも遊べます。
最後に一つだけ聞きたいのは、
この 7 日間で作った中で、
「自分的に一番気に入っているポイント」はどこか、
ということです。
そこに、あなたの“開発者としての好み”が
もうちゃんと顔を出しています。

