Day28 前半のゴール
ここまでで、TODOアプリは「追加・削除・保存・復元」までできるようになりました。
Day28 のテーマは 完了機能。
前半でやるのは、ざっくり言うとこの2つです。
タスクに「完了したかどうか」の情報を持たせる
その情報を画面(チェックボックス)に反映できる形にする
まだ「クリックして完了状態を切り替える」ところまでは行きません。
まずは データの形を整えること に集中します。
完了機能を日本語で分解してみる
ただ「チェックを付ける」だけでは足りない
「完了機能を付けたい」と聞くと、
多くの人は「チェックボックスを置けばいいんでしょ?」と思います。
でも、アプリとしてちゃんと動かすには、もう少し分解が必要です。
タスクごとに「完了しているかどうか」を覚えておく
その状態を画面に反映する(チェックの ON/OFF)
後で localStorage にも完了状態を含めて保存したい
つまり、見た目だけじゃなくて、データ側にも完了フラグが必要になります。
いまの tasks の形を見直す
文字列だけでは「完了」を表現できない
Day27 までの tasks は、こんな形でした。
let tasks = ["買い物に行く", "メールを送る"];
JavaScriptこれは「タスクの名前」しか持っていません。
ここに「完了したかどうか」を足そうとすると、
文字列だけではどうにもなりません。
そこで、「タスク1件」を オブジェクト で表現することにします。
タスク1件をオブジェクトで表す
title と isDone を持つ形にする
タスク1件を、こういう形にします。
const task = {
title: "買い物に行く",
isDone: false
};
JavaScripttitle
タスクの内容(今までの文字列)
isDone
完了しているかどうか(true / false)
これを配列にすると、こうなります。
let tasks = [
{ title: "買い物に行く", isDone: false },
{ title: "メールを送る", isDone: true }
];
JavaScriptこの形にしておくと、
完了したタスクだけ見た目を変える
完了状態も含めて localStorage に保存する
後で「完了だけ表示」みたいな機能も付けられる
といった拡張が、自然にできるようになります。
addTask をオブジェクト対応に書き換える
文字列ではなく「タスクオブジェクト」を追加する
今までの addTask はこうでした。
function addTask(text) {
tasks.push(text);
}
JavaScriptこれを、オブジェクトを追加する形に変えます。
function addTask(text) {
const task = {
title: text,
isDone: false
};
tasks.push(task);
}
JavaScriptここでのポイントは、
新しく作られるタスクは必ず isDone: false から始まる
ということです。
「最初は未完了、あとで完了に変える」という流れが、ここで決まります。
renderTasks を「オブジェクト前提」に書き換える
task.title を表示に使う
今までは、forEach の中で text を受け取っていました。
tasks.forEach((text, index) => {
// text を使って表示
});
JavaScriptこれを、オブジェクト前提に変えます。
tasks.forEach((task, index) => {
// task.title を使って表示
});
JavaScript具体的にはこうです。
function renderTasks() {
taskListElement.textContent = "";
tasks.forEach((task, index) => {
const taskItemElement = document.createElement("div");
const taskTextElement = document.createElement("span");
taskTextElement.textContent = task.title;
const deleteButtonElement = document.createElement("button");
deleteButtonElement.textContent = "削除";
deleteButtonElement.addEventListener("click", () => {
deleteTask(index);
saveTasks();
renderTasks();
});
taskItemElement.appendChild(taskTextElement);
taskItemElement.appendChild(deleteButtonElement);
taskListElement.appendChild(taskItemElement);
});
}
JavaScriptここで大事なのは、
tasks の中身が「文字列」から「オブジェクト」に変わった
それに合わせて、表示も task.title に変えた
という 2 点です。
isDone はまだ使っていませんが、「いつでも使える状態」にはなりました。
完了チェック用の UI を追加する
チェックボックスをタスクの左に置く
完了機能の UI として、一番分かりやすいのはチェックボックスです。
タスク1件の中に、チェックボックスを追加します。
function renderTasks() {
taskListElement.textContent = "";
tasks.forEach((task, index) => {
const taskItemElement = document.createElement("div");
const checkboxElement = document.createElement("input");
checkboxElement.type = "checkbox";
const taskTextElement = document.createElement("span");
taskTextElement.textContent = task.title;
const deleteButtonElement = document.createElement("button");
deleteButtonElement.textContent = "削除";
taskItemElement.appendChild(checkboxElement);
taskItemElement.appendChild(taskTextElement);
taskItemElement.appendChild(deleteButtonElement);
taskListElement.appendChild(taskItemElement);
});
}
JavaScriptこれで見た目は、
[ ] 買い物に行く 削除
[ ] メールを送る 削除
のようになります。
まだチェックと isDone は連動していませんが、
「完了機能の入り口」はできました。
isDone とチェック状態を結びつける
データの状態を UI に反映する
次に、「完了しているタスクは最初からチェックが付いている」状態にします。
checkboxElement.checked = task.isDone;
JavaScriptこれを renderTasks の中に追加します。
const checkboxElement = document.createElement("input");
checkboxElement.type = "checkbox";
checkboxElement.checked = task.isDone;
JavaScriptこれで、
isDone が true のタスク → チェック付き
isDone が false のタスク → チェックなし
という表示になります。
ここでようやく、
データ(task.isDone)
↓
UI(checkbox.checked)
という「一方向のつながり」ができました。
まだ「クリックして isDone を変える」処理は書いていません。
前半のゴールはあくまで、
タスクをオブジェクトにする
完了フラグ isDone を持たせる
isDone に応じてチェック状態を反映する
ここまでです。
Day28 前半のコードイメージ
追加・削除・保存はそのまま、タスク構造だけ進化させる
前半の時点でのイメージをまとめると、こんな感じです。
let tasks = [];
function addTask(text) {
const task = {
title: text,
isDone: false
};
tasks.push(task);
}
function renderTasks() {
taskListElement.textContent = "";
tasks.forEach((task, index) => {
const taskItemElement = document.createElement("div");
const checkboxElement = document.createElement("input");
checkboxElement.type = "checkbox";
checkboxElement.checked = task.isDone;
const taskTextElement = document.createElement("span");
taskTextElement.textContent = task.title;
const deleteButtonElement = document.createElement("button");
deleteButtonElement.textContent = "削除";
deleteButtonElement.addEventListener("click", () => {
deleteTask(index);
saveTasks();
renderTasks();
});
taskItemElement.appendChild(checkboxElement);
taskItemElement.appendChild(taskTextElement);
taskItemElement.appendChild(deleteButtonElement);
taskListElement.appendChild(taskItemElement);
});
}
JavaScriptまだ完了状態の切り替えはしません。
でも、「完了機能を載せるための土台」はここでほぼ完成しています。
Day28 前半のまとめ
前半で本当に押さえてほしいのは、この5つです。
タスクは「文字列」ではなく「オブジェクト」で持つ
オブジェクトには title と isDone を持たせる
addTask はオブジェクトを追加するように書き換える
renderTasks は task.title と task.isDone を使う
チェックボックスを表示し、isDone に応じて checked を設定する
後半では、この土台の上に、
チェックをクリックしたら isDone を切り替える
完了タスクの見た目を変える(取り消し線など)
完了状態も含めて localStorage に保存・復元する
という「完了機能の本体」を一緒に作っていきます。
