JavaScript | 1 日 90 分 × 7 日アプリ学習:簡単 ToDo アプリ(初級編)

JavaScript
スポンサーリンク

4日目のゴールと今日のテーマ

4日目のテーマは「同じ機能なのに“設計が一段きれいになった ToDo アプリ”を体で感じること」です。
機能としてはまだ、追加・一覧表示・全消去だけです。

でも今日は、

配列を「ただの一覧」ではなく「タスクのコレクション」として扱う。
再描画を“アプリの中心”として位置づけなおす。
コードを「意味ごとにきれいに分けて」読みやすくする。

この3つを意識します。
新しい派手な機能より、「土台を固める日」です。


ここまでの ToDo アプリを一度“設計図”として見る

タスクの持ち方を整理しておく

2日目までのタスクの形はこうでした。

let todos = [
  { text: "買い物に行く" },
  { text: "勉強する" }
];
JavaScript

ひとつひとつのタスクは { text: "…" } というオブジェクト。
それが配列 todos に並んでいる、という構造です。

ここで大事なのは「タスク1件=オブジェクト1つ」という意識です。
今は text だけですが、将来 iddone フラグを増やしたくなったら、このオブジェクトに足していけば良いだけ、という拡張性があります。

再描画の役目をもう一度確認する

render 関数は、こんなイメージでした。

function createTodoElement(todo) {
  const itemEl = document.createElement("div");
  itemEl.textContent = todo.text;
  return itemEl;
}

function render() {
  listEl.textContent = "";

  todos.forEach((todo) => {
    const itemEl = createTodoElement(todo);
    listEl.appendChild(itemEl);
  });
}
JavaScript

やっていることは「配列 todos を全部読む → 画面を作り直す」だけです。
状態を書き換えない、入力欄に触らない、他の要素もいじらない。
この“純粋さ”が今日の主役です。


4日目のテーマ①:配列を「アプリの真実」として固定する

状態の本体はどこか、をハッキリさせる

改めて整理すると、今のアプリには「状態」が二つあります。

ひとつは配列 todos
もうひとつは画面に表示されているタスクの一覧。

ここで設計として重要なのは、

正しいのは「配列 todos」だけ。
画面はそれを映しているだけ。

というルールを守り切ることです。

例えば、タスクを追加したいときに「画面に直接要素を足す」のではなく、

配列に push する。
その後に render で画面を作り直す。

という流れを徹底する。
この“徹底”そのものが、設計としての強さになります。

追加・全消去も、配列基準で考え直す

追加はこうでした。

function handleAdd() {
  const text = inputEl.value.trim();
  if (text === "") {
    return;
  }

  const todo = { text: text };
  todos.push(todo);

  inputEl.value = "";
  render();
}
JavaScript

配列に新しいタスクを追加してから render。
画面はいじっていません。

全消去はこうでした。

function handleClear() {
  todos = [];
  render();
}
JavaScript

配列を空にしてから render。
やっぱり、画面はいじりません。

この「状態の本体を配列に集中させている」という構図を意識できていると、
この先機能を増やしてもブレにくくなります。


4日目のテーマ②:再描画を“アプリの中心”として扱う

render を「最後に必ず通す」ゲートにする

今のアプリでは、画面を変えたいときは必ず render を呼びます。
この「必ずここを通る」というゲートがあると、いくつか良いことが起こります。

まず、「画面の状態は always render の結果」である、と言い切れる。
つまり、バラバラに画面を書き換えて状態がズレる、という事故が減ります。

もうひとつは、「何かバグったときに render を見ればよい」という目印があること。
配列 todos も、render も、見れば今の状況が理解できる。
これはコードを“読む未来の自分”へのプレゼントです。

「view 層」としての render を意識する

言葉の話になりますが、今の構造はこんな分担です。

配列 todos
→ アプリの「モデル」(状態、データ)

render
→ アプリの「ビュー」(見た目)

イベントハンドラ(handleAdd / handleClear など)
→ アプリの「コントローラ」(どう状態を変えるかを決める)

いきなり MVC を完璧に理解しなくても大丈夫です。
大事なのは、

状態(配列)
見た目(render)
操作(イベントハンドラ)

が、なんとなく役割ごとに分かれてきている、という感覚です。


4日目のテーマ③:コードを“意味ごとにかたまり”として整理する

今の関数たちを役割でグループ分けしてみる

関数を意味ごとに分けると、だいたいこうなります。

見た目関連

  • createTodoElement
  • render

状態の変更

  • handleAdd
  • handleClear

入力・操作の入り口

  • handleKeyDown
  • クリックイベントの登録(setup の中)

このグループ分けが自分の中で見えていると、
「どこを触れば何が変わるか」がクリアになります。

例えば「表示の仕方を変えたい」ときは createTodoElement / render を見る。
追加のルール(空はダメにしたいなど)を変えたいときは handleAdd を見る。
Enter の挙動を変えたいときは handleKeyDown を見る。

コードの量はまだ少ないけれど、「役割ごとに分ける」という習慣はこの段階から育てるのが一番効きます。

setup で“アプリの入口”を1か所に

2日目の最後に、こんな setup を用意していました。

function setup() {
  addButton.addEventListener("click", handleAdd);
  clearButton.addEventListener("click", handleClear);
  inputEl.addEventListener("keydown", handleKeyDown);
  render();
}

setup();
JavaScript

ここでやっていることは、「アプリが動き始めるときに必要なこと」をまとめる、です。

イベント登録。
初期描画。

この二つが、アプリの“起動処理”です。

ファイルの最後に setup(); と1行あるだけで、
「ここからアプリがスタートするんだな」がひと目で分かる。
これもまた、“未来の自分への優しさ”です。


4日目の小さな発展:見た目をちょっと変えても設計が崩れない感覚

例えば、タスクの並びを変えたくなったら

今は追加したタスクが下に増えていく形ですが、
「新しいタスクを上に表示したい」と思ったとします。

配列をこう変えてもいいし、

todos.unshift(todo);
JavaScript

render の中で、配列を逆順に回してもいいです。

function render() {
  listEl.textContent = "";

  [...todos].reverse().forEach((todo) => {
    const itemEl = createTodoElement(todo);
    listEl.appendChild(itemEl);
  });
}
JavaScript

ここで見てほしいのは、

「どんな表示順にしても、“配列 → render → 画面” の構造は崩れない」

ということです。

タスクの見た目を変えたいときは createTodoElement を変える。
並べ方を変えたいときは render を変える。
追加のルールを変えたいときは handleAdd を変える。

こうやって、「触る場所が明確に分かれている」というのが設計の強さです。


4日目の全体像(あらためてコードを設計として眺める)

今のアプリの骨組みを、設計目線で眺めてみます。

const inputEl = document.getElementById("todo-input");
const addButton = document.getElementById("add-button");
const clearButton = document.getElementById("clear-button");
const listEl = document.getElementById("todo-list");

let todos = [];

function createTodoElement(todo) {
  const itemEl = document.createElement("div");
  itemEl.textContent = todo.text;
  return itemEl;
}

function render() {
  listEl.textContent = "";

  todos.forEach((todo) => {
    const itemEl = createTodoElement(todo);
    listEl.appendChild(itemEl);
  });
}

function handleAdd() {
  const text = inputEl.value.trim();
  if (text === "") {
    return;
  }

  const todo = { text: text };
  todos.push(todo);

  inputEl.value = "";
  render();
}

function handleClear() {
  todos = [];
  render();
}

function handleKeyDown(event) {
  if (event.key === "Enter") {
    handleAdd();
  }
}

function setup() {
  addButton.addEventListener("click", handleAdd);
  clearButton.addEventListener("click", handleClear);
  inputEl.addEventListener("keydown", handleKeyDown);
  render();
}

setup();
JavaScript

上から順に読むと、

要素の取得。
状態(todos)。
見た目の定義。
状態変更の処理。
入力イベントの処理。
初期化処理。

という流れになっていることが分かると思います。
これ、もう立派に「設計された簡単 ToDo アプリ」です。


4日目のまとめと、5日目へのつなぎ

今日のポイントを言葉で整理します。

配列 todos を「アプリの真実の状態」として固定し、画面は常にそれを映すだけにしていると意識できた。
追加・全消去などの操作は、必ず「配列を変える」→「render を呼ぶ」という流れに乗せている。
render を「配列を読むだけの安全な関数」として設計し、“いつ呼んでも大丈夫”な存在にした。
関数を役割ごとにグループ分けして、「どこを触れば何が変わるか」が見えるようになってきた。
setup でアプリの起動処理を1か所にまとめ、「コード全体を上から下までストーリーとして読める」形になった。

5日目以降は、この土台の上に、

1件削除(特定のタスクだけ配列から消す)
完了フラグ(done を持たせて見た目で区別する)
ID でタスクを特定する

といった、「ToDo アプリらしい機能」を少しずつ足していきます。

最後にひとつ、ちゃんと聞きたい。

今日の中で、「あ、自分これ分かってきたかも」と感じたところはどこでしたか?
配列を“真実”にして画面を結果と見なした瞬間か、
render が「配列 → 画面」の変換係だとストンときた瞬間か、
関数たちの役割がふっと見えた瞬間か。

その“分かってきた感覚”が、あなたのアプリ設計の芯になります。
それを意識したまま、5日目の ToDo 強化に進んでいきましょう。

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