基礎から学ぶJavaScript入門 90日コース | Webページを操作するDOM - Day 38:要素の削除

JavaScript 90日で身につけるJavaScript
スポンサーリンク
スポンサーリンク

Day 38:要素の削除(前半)

「remove() を使って“不要になった要素を安全に消す”ToDo削除機能の基礎を身につける」

Day 38 前半では、DOM操作の中でもとても重要な 要素の削除 を扱います。 前日までで「要素を追加する」力を身につけましたが、Webアプリケーションでは 追加と同じくらい削除が重要 です。

今回のキーワードは remove()。 実践テーマは ToDo削除機能 です。

remove() の本質

要素自身が「自分を DOM から取り除く」

remove() はとてもシンプルで強力です。

要素.remove();
JavaScript

これだけで、その要素は DOM ツリーから完全に消えます。

  • 親要素を指定する必要がない
  • removeChild() より直感的
  • 「この要素を消したい」という意図がそのままコードになる

ToDo削除機能では、

「削除ボタンが押されたら、そのボタンが属している ToDo(li)を消す」

という流れで使います。

ToDo削除機能をステップで設計する

削除機能は、次のステップで考えると理解しやすくなります。

Step 1:ToDo項目(li)を作る

ToDo項目は、

  • テキスト
  • 削除ボタン

を含む ひとまとまりの部品 として作ります。

Step 2:削除ボタンにイベントを付ける

削除ボタンが押されたら、

liElement.remove();
JavaScript

でその項目を削除します。

Step 3:フォーム送信で ToDo を追加する

前日までの「要素追加」と組み合わせて、 追加 → 削除 の流れを完成させます。

ToDo削除機能の基本コード(初心者向けコメント付き)

<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <title>Day 38 前半:ToDo削除機能</title>
</head>
<body>
  <h1>ToDoリスト(削除機能付き)</h1>

  <!-- ▼ ToDoリスト -->
  <ul id="todoList">
    <!-- ここに<li>が追加されていきます -->
  </ul>

  <!-- ▼ ToDo追加フォーム -->
  <form id="todoForm">
    <label for="todoInput">ToDo:</label>
    <input type="text" id="todoInput" placeholder="やることを入力してください">
    <button type="submit">追加</button>
  </form>

  <!-- ▼ メッセージ表示エリア -->
  <p id="message"></p>

  <script>
    // ▼ DOM要素の取得
    const todoListElement = document.getElementById('todoList');
    const todoFormElement = document.getElementById('todoForm');
    const todoInputElement = document.getElementById('todoInput');
    const messageElement = document.getElementById('message');

    // ▼ ToDo項目(削除ボタン付き)を作る関数
    function createTodoItem(text) {
      // <li>を作る
      const liElement = document.createElement('li');

      // テキスト部分
      const textSpan = document.createElement('span');
      textSpan.textContent = text; // 安全にテキストとして扱う

      // 削除ボタン
      const deleteButton = document.createElement('button');
      deleteButton.textContent = '削除';

      // ▼ 削除ボタンが押されたときの処理
      deleteButton.addEventListener('click', function () {
        liElement.remove(); // この<li>を削除する
        console.log('ToDoを削除:', text);
      });

      // ▼ li の中にテキストと削除ボタンを追加
      liElement.append(textSpan, deleteButton);

      return liElement;
    }

    // ▼ ToDoをリストに追加する関数
    function addTodoToList(listElement, text) {
      const trimmedText = text.trim();

      if (trimmedText === '') {
        messageElement.textContent = 'ToDoが空です。やることを入力してください。';
        return;
      }

      const liElement = createTodoItem(trimmedText);
      listElement.appendChild(liElement);

      messageElement.textContent = `「${trimmedText}」を追加しました。`;
    }

    // ▼ フォーム送信時の処理
    todoFormElement.addEventListener('submit', function (event) {
      event.preventDefault(); // ページリロードを防ぐ

      const enteredTodo = todoInputElement.value;
      messageElement.textContent = '';

      addTodoToList(todoListElement, enteredTodo);

      todoInputElement.value = ''; // 入力欄をリセット
    });
  </script>
</body>
</html>

remove() を深掘りする

remove() のメリット

  • 親要素を意識しなくてよい
  • コードが短くなる
  • 「この要素を消す」という意図が明確
  • 初心者でも直感的に理解できる

remove() の注意点

  • 完全に削除されるため、元に戻すには別の仕組みが必要
  • 「削除してよいもの」だけに使うことが大切

セキュリティの観点

ToDo削除機能では、ユーザー入力を画面に表示します。 その際、必ず textContent を使います。

textSpan.textContent = text;
JavaScript

これにより、

  • <script> などが入力されても実行されない
  • HTMLとして解釈されず安全

というメリットがあります。

初心者の段階では、

ユーザー入力を画面に出すときは textContent を使う

という習慣を持つことがとても重要です。

Day 38 前半 練習用テンプレート

<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <title>Day 38 前半:要素の削除 練習テンプレート</title>
</head>
<body>
  <h1>削除機能付きToDoリスト(練習用)</h1>

  <ul id="todoList"></ul>

  <form id="todoForm">
    <input type="text" id="todoInput" placeholder="ToDoを入力">
    <button type="submit">追加</button>
  </form>

  <p id="message"></p>

  <script>
    const todoListElement = document.getElementById('todoList');
    const todoFormElement = document.getElementById('todoForm');
    const todoInputElement = document.getElementById('todoInput');
    const messageElement = document.getElementById('message');

    function createTodoItem(text) {
      const li = document.createElement('li');
      const span = document.createElement('span');
      span.textContent = text;

      const btn = document.createElement('button');
      btn.textContent = '削除';

      btn.addEventListener('click', () => li.remove());

      li.append(span, btn);
      return li;
    }

    todoFormElement.addEventListener('submit', (event) => {
      event.preventDefault();

      const text = todoInputElement.value.trim();
      messageElement.textContent = '';

      if (text === '') {
        messageElement.textContent = '入力が空です。';
        return;
      }

      todoListElement.appendChild(createTodoItem(text));
      todoInputElement.value = '';
    });
  </script>
</body>
</html>

Day 38 前半のまとめ

  • remove() は「要素自身が自分を DOM から削除する」シンプルで強力なメソッド
  • ToDo削除機能では、削除ボタンのイベント内で liElement.remove() を使う
  • 要素追加と削除が揃うことで、Webアプリとしての完成度が一気に上がる
  • ユーザー入力は必ず textContent で扱い、安全性を確保する

Day 38:要素の削除(後半)

「remove() を“ちゃんと設計して使う”ToDo削除機能の実践編」

Day 38後半では、前半で学んだ remove() を、 「実際に使えるToDo削除機能」 に育てていくことを目指します。

前半では、

  • 削除ボタンを押したら、その項目(<li>)を remove() で消す

という基本を学びました。 後半では、そこから一歩進めて、

  • コードを整理して読みやすくする
  • 「本当に消していいか」を確認する
  • 完了状態と削除を分けて考える

といった、現場で使える削除機能の設計を体験していきます。

削除機能を“設計する目線”で考える

ただ消すだけの削除と、ちゃんと設計された削除

削除機能には、ざっくり2種類あります。

  • ただ消す削除
    • ボタンを押したら即削除
    • シンプルだが、誤操作に弱い
  • 設計された削除
    • 確認ダイアログを出す
    • 完了状態と削除を分ける
    • ログを残す、など

今回のToDo削除機能では、

  1. 削除ボタン付きToDo項目を作る
  2. 削除前に確認ダイアログを出す
  3. 完了チェックと削除を分ける

という流れで、「ちゃんと設計された削除」を練習していきます。

基本の削除機能をもう一度整理する

remove() の役割を再確認する

remove() は、

「その要素自身を、DOMツリーから完全に取り除く」

メソッドです。

liElement.remove();
JavaScript

と書くだけで、その <li> は画面から消えます。 親要素を意識する必要がないので、 削除ボタン付きのToDo項目とは非常に相性が良いです。

実践①:確認ダイアログ付きの削除機能

「本当に削除してよいか」をユーザーに聞く

誤操作を防ぐために、 削除前に confirm() を使って確認するパターンを作ってみます。

deleteButton.addEventListener('click', function () {
  const isOk = confirm(`「${text}」を本当に削除しますか?`);

  if (!isOk) {
    // キャンセルされた場合は何もしません
    return;
  }

  liElement.remove();
  console.log('ToDoを削除しました:', text);
});
JavaScript

confirm() は、

  • OK → true
  • キャンセル → false

を返すダイアログです。

これを使うことで、

「うっかり削除してしまった」

という事故を減らすことができます。

確認付きToDo削除機能の完成コード

<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <title>Day 38 後半:確認付きToDo削除機能</title>
</head>
<body>
  <h1>確認付きToDoリスト</h1>

  <ul id="todoList"></ul>

  <form id="todoForm">
    <label for="todoInput">ToDo:</label>
    <input type="text" id="todoInput" placeholder="やることを入力してください">
    <button type="submit">追加</button>
  </form>

  <p id="message"></p>

  <script>
    const todoListElement = document.getElementById('todoList');
    const todoFormElement = document.getElementById('todoForm');
    const todoInputElement = document.getElementById('todoInput');
    const messageElement = document.getElementById('message');

    // ▼ 確認付き削除ボタンを持つ<li>を作る関数
    function createTodoItem(text) {
      const liElement = document.createElement('li');

      const textSpan = document.createElement('span');
      textSpan.textContent = text; // ユーザー入力を安全にテキストとして扱います

      const deleteButton = document.createElement('button');
      deleteButton.textContent = '削除';

      deleteButton.addEventListener('click', function () {
        const isOk = confirm(`「${text}」を本当に削除しますか?`);

        if (!isOk) {
          // キャンセルされた場合は何もしない
          return;
        }

        liElement.remove(); // この<li>を削除
        console.log('ToDo削除:', text);
      });

      liElement.append(textSpan, deleteButton);

      return liElement;
    }

    function addTodoToList(listElement, text) {
      const trimmedText = text.trim();

      if (trimmedText === '') {
        messageElement.textContent = 'ToDoが空です。やることを入力してください。';
        return;
      }

      const liElement = createTodoItem(trimmedText);
      listElement.appendChild(liElement);

      messageElement.textContent = `「${trimmedText}」を追加しました。`;
    }

    todoFormElement.addEventListener('submit', function (event) {
      event.preventDefault();

      const enteredTodo = todoInputElement.value;
      messageElement.textContent = '';

      addTodoToList(todoListElement, enteredTodo);

      todoInputElement.value = '';
    });
  </script>
</body>
</html>

深掘りポイント

  • 削除ボタンのイベント処理の中で、 「確認 → 削除」という2段階の流れを作っていること。
  • remove() は「削除する」と決めた後の最後の一手として使う、 という意識を持つと、設計が安定します。

実践②:完了チェックと削除を分ける

「終わったToDo」と「消したいToDo」は違う

現実のToDo管理では、

  • 終わったけれど、履歴として残しておきたい
  • 完了したものは薄く表示したい
  • 本当に不要になったものだけ削除したい

というニーズがあります。

そこで、

  1. チェックボックスで「完了」を表現する
  2. 完了したものだけ削除対象にする

という設計を試してみます。

完了チェック付きToDo項目を作る

function createTodoItemWithDone(text) {
  const liElement = document.createElement('li');

  const doneCheckbox = document.createElement('input');
  doneCheckbox.type = 'checkbox';

  const textSpan = document.createElement('span');
  textSpan.textContent = text;

  const deleteButton = document.createElement('button');
  deleteButton.textContent = '削除';

  // ▼ 完了チェックが変更されたときの処理
  doneCheckbox.addEventListener('change', function () {
    if (doneCheckbox.checked) {
      // 完了したら、見た目を少し薄くする
      textSpan.style.textDecoration = 'line-through';
      textSpan.style.color = '#888';
    } else {
      // 未完了に戻したら、元に戻す
      textSpan.style.textDecoration = 'none';
      textSpan.style.color = '';
    }
  });

  // ▼ 削除ボタンが押されたときの処理
  deleteButton.addEventListener('click', function () {
    if (!doneCheckbox.checked) {
      alert('完了チェックを付けてから削除してください。');
      return;
    }

    liElement.remove();
    console.log('完了済みToDo削除:', text);
  });

  liElement.append(doneCheckbox, textSpan, deleteButton);

  return liElement;
}
JavaScript

ここでは、

  • チェックボックスで「完了状態」を持たせる
  • 完了していないものは削除させない

というルールを設計しています。

完了チェック+削除のToDoリスト完成コード

<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <title>Day 38 後半:完了チェック付きToDo削除</title>
</head>
<body>
  <h1>完了チェック付きToDoリスト</h1>

  <ul id="todoList"></ul>

  <form id="todoForm">
    <label for="todoInput">ToDo:</label>
    <input type="text" id="todoInput" placeholder="やることを入力してください">
    <button type="submit">追加</button>
  </form>

  <p id="message"></p>

  <script>
    const todoListElement = document.getElementById('todoList');
    const todoFormElement = document.getElementById('todoForm');
    const todoInputElement = document.getElementById('todoInput');
    const messageElement = document.getElementById('message');

    function createTodoItemWithDone(text) {
      const liElement = document.createElement('li');

      const doneCheckbox = document.createElement('input');
      doneCheckbox.type = 'checkbox';

      const textSpan = document.createElement('span');
      textSpan.textContent = text;

      const deleteButton = document.createElement('button');
      deleteButton.textContent = '削除';

      doneCheckbox.addEventListener('change', function () {
        if (doneCheckbox.checked) {
          textSpan.style.textDecoration = 'line-through';
          textSpan.style.color = '#888';
        } else {
          textSpan.style.textDecoration = 'none';
          textSpan.style.color = '';
        }
      });

      deleteButton.addEventListener('click', function () {
        if (!doneCheckbox.checked) {
          alert('完了チェックを付けてから削除してください。');
          return;
        }

        liElement.remove();
        console.log('完了済みToDo削除:', text);
      });

      liElement.append(doneCheckbox, textSpan, deleteButton);

      return liElement;
    }

    function addTodoToList(listElement, text) {
      const trimmedText = text.trim();

      if (trimmedText === '') {
        messageElement.textContent = 'ToDoが空です。やることを入力してください。';
        return;
      }

      const liElement = createTodoItemWithDone(trimmedText);
      listElement.appendChild(liElement);

      messageElement.textContent = `「${trimmedText}」を追加しました。`;
    }

    todoFormElement.addEventListener('submit', function (event) {
      event.preventDefault();

      const enteredTodo = todoInputElement.value;
      messageElement.textContent = '';

      addTodoToList(todoListElement, enteredTodo);

      todoInputElement.value = '';
    });
  </script>
</body>
</html>

深掘りポイント

  • 「完了」と「削除」を分けることで、 ユーザーの操作に意味を持たせていること。
  • remove() は「最後の出口」として使い、 その前に「本当に削除してよいか」をロジックでチェックしていること。

こうした設計は、 現場のアプリケーションでもよく使われるパターンです。

セキュリティ・安全性の観点からの補足

ToDo削除機能では、

  • ユーザー入力を画面に表示する
  • ユーザー操作で要素を削除する

という動きがあります。

安全性のために、次のポイントを意識しておくと良いです。

  • 入力値を表示するときは、必ず textContent を使う
    • innerHTML を使うと、入力された文字列がHTMLとして解釈されてしまい、 <script> などが実行される危険があります。
  • 削除はフロント側の見た目の話であり、 本当にデータを消すかどうかはサーバー側の設計次第であること。

今回のコードでは、

textSpan.textContent = text;
JavaScript

とすることで、 ユーザー入力が安全に「ただのテキスト」として扱われています。

Day 38 後半 練習用テンプレート

最後に、今日の内容をまとめて練習できるテンプレートを紹介します。

<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <title>Day 38 後半:要素の削除 総合練習テンプレート</title>
</head>
<body>
  <h1>Day 38 後半:要素の削除 総合練習</h1>

  <section>
    <h2>確認付き&完了チェック付きToDoリスト</h2>

    <ul id="todoList"></ul>

    <form id="todoForm">
      <label for="todoInput">ToDo:</label>
      <input type="text" id="todoInput" placeholder="やることを入力してください">
      <button type="submit">追加</button>
    </form>

    <p id="message"></p>
  </section>

  <script>
    console.log('--- 要素の削除 総合練習開始 ---');

    const todoListElement = document.getElementById('todoList');
    const todoFormElement = document.getElementById('todoForm');
    const todoInputElement = document.getElementById('todoInput');
    const messageElement = document.getElementById('message');

    function createTodoItem(text) {
      const liElement = document.createElement('li');

      const doneCheckbox = document.createElement('input');
      doneCheckbox.type = 'checkbox';

      const textSpan = document.createElement('span');
      textSpan.textContent = text;

      const deleteButton = document.createElement('button');
      deleteButton.textContent = '削除';

      doneCheckbox.addEventListener('change', function () {
        if (doneCheckbox.checked) {
          textSpan.style.textDecoration = 'line-through';
          textSpan.style.color = '#888';
        } else {
          textSpan.style.textDecoration = 'none';
          textSpan.style.color = '';
        }
      });

      deleteButton.addEventListener('click', function () {
        const isOk = confirm(`「${text}」を本当に削除しますか?`);

        if (!isOk) {
          return;
        }

        if (!doneCheckbox.checked) {
          alert('完了チェックを付けてから削除してください。');
          return;
        }

        liElement.remove();
        console.log('ToDo削除:', text);
      });

      liElement.append(doneCheckbox, textSpan, deleteButton);

      return liElement;
    }

    function addTodoToList(listElement, text) {
      const trimmedText = text.trim();

      if (trimmedText === '') {
        messageElement.textContent = 'ToDoが空です。やることを入力してください。';
        return;
      }

      const liElement = createTodoItem(trimmedText);
      listElement.appendChild(liElement);

      messageElement.textContent = `「${trimmedText}」を追加しました。`;
      console.log('ToDo追加:', trimmedText);
    }

    todoFormElement.addEventListener('submit', function (event) {
      event.preventDefault();

      const enteredTodo = todoInputElement.value;
      messageElement.textContent = '';

      addTodoToList(todoListElement, enteredTodo);

      todoInputElement.value = '';
    });

    console.log('--- 要素の削除 総合練習テンプレートの準備が完了しました ---');
  </script>
</body>
</html>

Day 38 後半のまとめ

Day 38後半では、

  • remove() を「ただ消す」だけでなく、 確認や完了チェックと組み合わせて設計する感覚を身につけたこと。
  • ToDo削除機能を通して、 「いつ・どの要素を・どんな条件で削除するか」を自分で決める練習をしたこと。
  • ユーザー入力を扱うときに、 textContent を使って安全性を確保する視点を維持したこと。

を整理しました。

この「削除をちゃんと設計する」感覚は、 通知の消去、メッセージの削除、カードの閉じるボタンなど、 多くのUIでそのまま活かせます。

今日のコードを何度か書き直しながら、

「削除は“最後の出口”だからこそ、慎重に設計する」

という意識を持って練習していくことで、 DOMを“増やすだけでなく、きちんと片づける”力が、さらに深まっていきます。

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