Day26 前半のゴール
Day25 で「タスクを追加できる TODO アプリ」ができました。
Day26 のテーマは タスク削除の実装。
前半ではまず、
「どのタスクを消すか」をどう特定するか
削除ボタンをどう配置するか
配列と画面をどう連動させるか
ここを、できるだけシンプルな形で押さえていきます。
いきなりコードを書かずに「削除」を設計する
何を消すのかをはっきりさせる
「削除機能」と聞くと、ついこう思いがちです。
「ボタンを押したら、そのタスクを消す」
でも、プログラム的にはもう一歩踏み込んで考える必要があります。
どのタスクに対応するボタンが押されたのか
そのタスクは tasks 配列の何番目なのか
配列から消したあと、画面をどう更新するのか
この3つが見えていれば、削除機能は怖くありません。
前提となる TODO アプリの形を確認する
配列+描画の構造をおさらい
Day25 の後半で作った形は、ざっくり言うとこうでした。
const taskInputElement = document.getElementById("taskInput");
const addButtonElement = document.getElementById("addButton");
const taskListElement = document.getElementById("taskList");
let tasks = [];
function addTask(text) {
tasks.push(text);
}
function renderTasks() {
taskListElement.textContent = "";
tasks.forEach((text) => {
const taskElement = document.createElement("p");
taskElement.textContent = text;
taskListElement.appendChild(taskElement);
});
}
addButtonElement.addEventListener("click", () => {
const text = taskInputElement.value.trim();
if (text === "") {
return;
}
addTask(text);
renderTasks();
taskInputElement.value = "";
});
JavaScriptここで重要なのは、
タスクの本体は tasks 配列
画面は renderTasks で配列から再構築
という構造になっていることです。
削除機能は、この「配列をいじってから再描画する」という流れに乗せて作ります。
削除ボタンをどこに置くかを決める
各タスクの横に「削除」ボタンを付ける
削除の UI として一番分かりやすいのは、
タスクの右側に「削除」ボタンを置く
という形です。
つまり、1つのタスクは
テキスト
削除ボタン
のセットになります。
これを renderTasks の中で作るイメージを持っておきましょう。
renderTasks を「削除ボタン付き」に書き換える
タスク1件分の「箱」を作る
まずは、タスク1件を包む要素を作ります。
p でも div でもいいですが、ここでは div を使ってみます。
function renderTasks() {
taskListElement.textContent = "";
tasks.forEach((text) => {
const taskItemElement = document.createElement("div");
const taskTextElement = document.createElement("span");
taskTextElement.textContent = text;
const deleteButtonElement = document.createElement("button");
deleteButtonElement.textContent = "削除";
taskItemElement.appendChild(taskTextElement);
taskItemElement.appendChild(deleteButtonElement);
taskListElement.appendChild(taskItemElement);
});
}
JavaScriptこの時点で、画面上は
タスクのテキスト + 削除ボタン
という形で並ぶようになります。
まだ削除は動きませんが、「見た目の準備」ができました。
どのタスクを削除するかを特定する
forEach の index を使う
削除ボタンが押されたときに必要なのは、
このボタンは tasks の何番目のタスクに対応しているのか
という情報です。
forEach には、第2引数として index(何番目か)が渡されます。
これを使って、「削除したいタスクの位置」を覚えさせます。
function renderTasks() {
taskListElement.textContent = "";
tasks.forEach((text, index) => {
const taskItemElement = document.createElement("div");
const taskTextElement = document.createElement("span");
taskTextElement.textContent = text;
const deleteButtonElement = document.createElement("button");
deleteButtonElement.textContent = "削除";
deleteButtonElement.addEventListener("click", () => {
console.log("削除ボタンが押されました。index:", index);
});
taskItemElement.appendChild(taskTextElement);
taskItemElement.appendChild(deleteButtonElement);
taskListElement.appendChild(taskItemElement);
});
}
JavaScriptこの状態でブラウザを開き、
タスクをいくつか追加してから削除ボタンを押すと、
コンソールに index が表示されます。
0 番目、1 番目、2 番目……
という情報が取れていれば、削除の準備はほぼ完了です。
配列からタスクを削除する
splice を使って「その1件だけ」を消す
配列から特定の位置の要素を削除するには、splice を使います。
tasks.splice(index, 1);
JavaScriptindex 番目から 1 件だけ削除する、という意味です。
さきほどの削除ボタンのイベントの中を、こう書き換えます。
deleteButtonElement.addEventListener("click", () => {
tasks.splice(index, 1);
renderTasks();
});
JavaScriptこれで、
削除ボタンが押される
対応する index のタスクが tasks から消える
renderTasks で画面を再描画する
という流れが完成します。
削除機能付き renderTasks の全体像
ここまでのコードをまとめる
前半のゴールとして、削除ボタン付きの renderTasks をまとめておきます。
function renderTasks() {
taskListElement.textContent = "";
tasks.forEach((text, index) => {
const taskItemElement = document.createElement("div");
const taskTextElement = document.createElement("span");
taskTextElement.textContent = text;
const deleteButtonElement = document.createElement("button");
deleteButtonElement.textContent = "削除";
deleteButtonElement.addEventListener("click", () => {
tasks.splice(index, 1);
renderTasks();
});
taskItemElement.appendChild(taskTextElement);
taskItemElement.appendChild(deleteButtonElement);
taskListElement.appendChild(taskItemElement);
});
}
JavaScriptこの関数は、
画面を一度クリアする
tasks を順番に見て、タスク1件分の要素を作る
テキストと削除ボタンをセットで配置する
削除ボタンには「自分の index を消す」処理を付ける
という役割を持っています。
デバッグの視点を少し足しておく
「どのタスクが消えたか」を確認する
もし削除がうまくいかないと感じたら、
削除イベントの中に console.log を入れてみてください。
deleteButtonElement.addEventListener("click", () => {
console.log("削除前 tasks:", tasks);
console.log("削除する index:", index);
tasks.splice(index, 1);
console.log("削除後 tasks:", tasks);
renderTasks();
});
JavaScriptこれで、
削除前に tasks がどうなっているか
どの index を消そうとしているか
削除後に tasks がどう変わったか
を一つずつ確認できます。
「配列がどう変わっているか」を意識して見る癖は、
この先もっと複雑なアプリを作るときにも必ず役に立ちます。
Day26 前半のまとめ
前半でやったことを整理すると、こうなります。
削除機能を「どのタスクを消すか」という視点から設計した
タスクの本体は tasks 配列で管理する前提を再確認した
renderTasks の中で、タスク1件分の要素(テキスト+削除ボタン)を作った
forEach の index を使って「削除対象の位置」を特定した
splice(index, 1) で配列からタスクを削除し、renderTasks で再描画した
後半では、この削除機能をもう少し整理して、
関数分割で削除処理を分ける
見た目やクラス名を整える
将来の「完了機能」や「保存機能」を見据えた形にする
というところまで一緒に進めていきます。
