1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

[JavaScript][L4] コンテンツ(div>ul>li)の生成機能を共通化(コンポーネント化)する

Last updated at Posted at 2024-11-16

実施条件

[JavaScript][L3] ボタン押下によりコンテンツ(div>ul>li)を別コンテンツ(div>ul>li)に移動(生成)するを理解していること

環境

MacBook Pro (2.3 GHz 8コアIntel Core i9)
macOS 14.0(23A344)
Homebrew 4.3.8
gh 2.52.0

共通化(コンポーネント化)する理由

  • onClickイベントを使って実装するとネストが深くなるため
  • 共通した機能は、共通化した方が保守性が上がるため

共通化(コンポーネント化)に至る状況

未完了のToDo(div)内に新たなコンテンツを生成する機能が以下の通り複数存在する

ソースコード外観

HTML

index.html
<!DOCTYPE html>
<html>
  <head>
    <title>TODO(JS)</title>
    <meta charset="UTF-8" />
  </head>

  <body>
    <div class="input-area">
      <input id="add-text" placeholder="TODOを入力" />
      <button id="add-button">追加</button>
    </div>
    <div class="incomplete-area">
      <p class="title">未完了のTODO</p>
      <ul id="incomplete-list">
        <!--  // 完成系の例としてliタグ以下を作成している
        <li>
          <div class="list-row">
            <p class="todo-item">TODOです</p>
            <button>完了</button>
            <button>削除</button>
          </div>
        </li> -->
      </ul>
    </div>
    <div class="complete-area">
      <p class="title">完了したTODO</p>
      <ul id="complete-list">
        <!--  // 完成系の例としてliタグ以下を作成している
        <li>
          <div class="list-row">
            <p class="todo-item">TODOでした</p>
            <button>戻す</button>
          </div>
        </li> -->
      </ul>
    </div>
    <script src="src/index.js"></script>
  </body>
</html>

JavaScript

index.js
import "./styles.css";

const onClickAdd = () => {
  // テキストボックスの値を取得し、初期化する
  const inputText = document.getElementById("add-text").value;
  document.getElementById("add-text").value = "";
  
  // 未完了リストに追加
  createIncompleteTodo(inputText);
  };

// 渡された引数を基に未完了のTODOを作成する関数
const createIncompleteTodo = (todo) => {
  // li生成
  const li = document.createElement("li");

  // div生成
  const div = document.createElement("div");
  div.className = "list-row";

  // p生成
  const p = document.createElement("p");
  p.className = "todo-item";
  p.innerText = todo;

  // button(完了)タグ生成
  const completeButton = document.createElement("button");
  completeButton.innerText = "完了";
  completeButton.addEventListener("click", () => {
    // 押された完了ボタンの親にあるliタグ配下の完了ボタンと削除ボタンを削除
    const moveTarget = completeButton.closest("li");
    completeButton.nextElementSibling.remove();
    completeButton.remove();
    // 戻すボタンを生成してdivタグ配下に設定
    const backButton = document.createElement("button");
    backButton.innerText = "戻す";
    moveTarget.firstElementChild.appendChild(backButton);
    // 完了リストに移動
    document.getElementById("complete-list").appendChild(moveTarget);
  });

  // button(削除)タグ生成
  const deleteButton = document.createElement("button");
  deleteButton.innerText = "削除";
  deleteButton.addEventListener("click", () => {
    // 押された削除ボタンの親にあるliタグを未完了リストから削除
    const deleteTarget = deleteButton.closest("li");
    document.getElementById("incomplete-list").removeChild(deleteTarget);
  });

  // liタグの子要素に各要素を設定
  div.appendChild(p);
  div.appendChild(completeButton);
  div.appendChild(deleteButton);
  li.appendChild(div);

  // id="incomplete-list"の`ul`タグに子要素を設定した`li`タグを追加
  document.getElementById("incomplete-list").appendChild(li);    
  };

document.getElementById("add-button").addEventListener("click", onClickAdd);

手順

  1. 共通化する関数のアロー関数を用意する

    index.js
    // 渡された引数を基に未完了のTODOを作成する関数
    const createIncompleteTodo = (todo) => {  
    };
    
  2. 既に存在しているコンテンツ(div>ul>li)を用意したアロー関数に貼り付ける

    index.js
    // 渡された引数を基に未完了のTODOを作成する関数
    const createIncompleteTodo = (todo) => {
    +   // li生成
    +   const li = document.createElement("li");
    + 
    +   // div生成
    +   const div = document.createElement("div");
    +   div.className = "list-row";
    + 
    +   // p生成
    +   const p = document.createElement("p");
    +   p.className = "todo-item";
    +   p.innerText = inputText;
    + 
    +   // button(完了)タグ生成
    +   const completeButton = document.createElement("button");
    +   completeButton.innerText = "完了";
    +   completeButton.addEventListener("click", () => {
    +     alert("完了");
    +   });
    + 
    +   // button(削除)タグ生成
    +   const deleteButton = document.createElement("button");
    +   deleteButton.innerText = "削除";
    +   deleteButton.addEventListener("click", () => {
    +     alert("削除");
    +   });
    + 
    +   // liタグの子要素に各要素を設定
    +   div.appendChild(p);
    +   div.appendChild(completeButton);
    +   div.appendChild(deleteButton);
    +   li.appendChild(div);
    + 
    +   // 未完了リストに追加
    +   document.getElementById("incomplete-list").appendChild(li);
    };
    
  3. 引数が揃っていないため修正する

    index.js
    // 渡された引数を基に未完了のTODOを作成する関数
    const createIncompleteTodo = (todo) => {
        // li生成
        const li = document.createElement("li");
      
        // div生成
        const div = document.createElement("div");
        div.className = "list-row";
      
        // p生成
        const p = document.createElement("p");
        p.className = "todo-item";
    -   p.innerText = inputText;
    +   p.innerText = todo;
    
  4. 既存のonClickイベントに共通化した関数を入れる

    index.js
    const onClickAdd = () => {
      // テキストボックスの値を取得し、初期化する
      const inputText = document.getElementById("add-text").value;
      document.getElementById("add-text").value = "";
    
    +   // 未完了リストに追加
    +   createIncompleteTodo(inputText);
    };
    

参考リンク

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?