개발조각

[JavaScript] 투두리스트 만들기(추가, 완료여부, 삭제) 본문

JavaScript

[JavaScript] 투두리스트 만들기(추가, 완료여부, 삭제)

개발조각 2023. 12. 4. 15:05
728x90
반응형

최근 어느 한 회사에서 코딩테스트를 보러 갔는데
인터넷 연결을 끊은 상태에서 40분 동안 html, css, javascript으로 투두리스트를 만드는 테스트였습니다.
(코딩 테스트라 해서 알고리즘인 줄 알았더니 과제테스트라 당황했다...)
 
리액트, 자동완성, 구글검색, chatGPT에 익숙해져 있는 나에게 인터넷 끊긴 상태로 javascript로만 만들라 하다니...
머릿속에는 아무런 기억이 나지 않았고, 노드 추가하는 방법이 기억이 안 나서 테스트를 망쳤습니다...ㅎㅎ
또 이런 일이 일어날 수도 있고, 이번기회에 javascript로만 투두리스트를 만들어보면 좋을 것 같습니다!!
 

이번에 만들어본 투두리스트는 JavaScript로만 만들었으며
리스트 추가, 완료여부확인 및 체크, 리스트 삭제 기능을 넣어서 만들어보았습니다. (로컬스토리지에 데이터를 담지는 않았습니다.)
css는 간단 요소만 작업했습니다.

 

구현화면


 
 

HTML


<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>투두리스트 만들기</title>
    <link rel="stylesheet" href="./index.css" />
    <script src="./index.js" defer></script>
  </head>
  <body>
    <div class="to_do_wrap">
      <h1>오늘의 할 일은?</h1>

      <form>
        <input type="text" />
        <button>+</button>
      </form>

      <ul class="list_wrap"></ul>
    </div>
  </body>
</html>
  • <script>태그의 defer속성은 페이지가 모두 로드된 후에 외부 스크립트가 실행됩니다.
  • <form>태그로 리스트 추가 시 기능 구현 예정

 

JavaScript 전체 코드


const form = document.querySelector("form");
const input = document.querySelector('input[type="text"]');
const ul = document.querySelector("ul");

// 리스트 완료 여부
const completeItem = (e) => {
  //   console.log(e.target.nextSibling);
  // 체크여부 확인
  const { checked } = e.target;
  // 체크버튼의 다음 형제요소 즉 span
  const target = e.target.nextSibling;

  // 체크여부 확인 후 true일 경우 span에 밑줄, false일 경우 span의 밑줄 없애기
  if (checked) {
    target.style.textDecoration = "line-through";
  } else {
    target.style.textDecoration = "";
  }
};

// 리스트 삭제
const delItem = (e) => {
  // 삭제버튼의 부모요소를 찾아오고 그 요소를 삭제해야 된다.
  const target = e.target.parentElement; // 지워야하는 리스트 요소
  target.remove();
};

// 리스트 추가
const addItem = (text) => {
  if (text) {
    const li = document.createElement("li");
    const div = document.createElement("div");
    const checkbox = document.createElement("input");
    checkbox.type = "checkbox";
    const span = document.createElement("span");
    const button = document.createElement("button");

    span.innerText = text;
    button.innerText = "삭제";

    // 리스트에 추가 할 때마다 추가된 리스트에는 리스트 완료 여부, 리스트 삭제 기능이 작동되어야 되기 때문에 추가 부분에 이벤트 작성
    // 체크버튼 클릭시 리스트 완료 여부 확인 및 표시
    checkbox.addEventListener("change", completeItem);

    // 삭제버튼 클릭시 해당 요소의 리스트 삭제
    button.addEventListener("click", delItem);

    // append():여러개 요소 추가, appendChile(): 한개 요소 추가
    div.append(checkbox, span);
    li.append(div, button);
    ul.appendChild(li);
  }
};

const handler = (e) => {
  e.preventDefault(); // 새로고침 방지

  // submit 할 때마다 리스트가 추가되기 때문에 submit부분에 이벤트 작성
  addItem(input.value);
  input.value = ""; // input 공백으로 초기화
};

form.addEventListener("submit", handler);

 
 

JavaScript 코드 분석


 

+버튼 클릭 시

const form = document.querySelector("form");
const input = document.querySelector('input[type="text"]');
const ul = document.querySelector("ul");

const handler = (e) => {
  e.preventDefault(); // 새로고침 방지

  // submit할 때마다 리스트가 추가되기 때문에 submit부분에 이벤트 작성
  addItem(input.value);
  input.value = ""; // input 공백으로 초기화
};

form.addEventListener("submit", handler);
  • 이벤트리스터를 등록할 때, 버튼의 클릭이 아닌 click이 아닌 form을 submit 할때 즉 제출될 때 지정
  • submit할 때마다 리스트가 추가되기 때문에 submit부분에 이벤트를 작성해야 된다.

 
form에서 submit이벤트 발생

  • form내부에 있는 input에서 엔터를 입력한 경우
  • form 내부에 있는 submit 타입의 버튼을 클릭한 경우

 

리스트 추가 기능

// 리스트 추가
const addItem = (text) => {
  if (text) {
    const li = document.createElement("li");
    const div = document.createElement("div");
    const checkbox = document.createElement("input");
    checkbox.type = "checkbox";
    const span = document.createElement("span");
    const button = document.createElement("button");

    span.innerText = text;
    button.innerText = "삭제";

    // append():여러개 요소 추가, appendChile(): 한개 요소 추가
    div.append(checkbox, span);
    li.append(div, button);
    ul.appendChild(li);
  }
};
  • ul안에 li를 추가하기 위해서는 createElement로 생성해 주고 appendChild, append로 원하는 위치에 태그를 추가해 주어야 된다.
  • innerText로 태그 안의 내용을 넣어주었다.

 
코드가 복잡해 보이지만 이 리스트 ui를 만들기 위해 이와 같이 작성했다.

<li>
    <div>
        <input type="checkbox">
        <span>잠자기</span>
    </div>
    <button>삭제</button>
</li>

 

완료여부 확인 및 체크하기

// 리스트 추가
const addItem = (text) => {
  if (text) {
    const li = document.createElement("li");
    ...

    span.innerText = text;
    button.innerText = "삭제";

    // 체크버튼 클릭시 리스트 완료 여부 확인 및 표시
    checkbox.addEventListener("change", completeItem);

    // 요소추가
    div.append(checkbox, span);
    li.append(div, button);
    ul.appendChild(li);
  }
};
  • 리스트에 추가할 때마다 추가된 리스트에는 완료 여부 기능이 작동되어야 되기 때문에 추가 부분에 이벤트 작성
// 리스트 완료 여부
const completeItem = (e) => {
  // 체크여부 확인
  const { checked } = e.target;
  // 체크버튼의 다음 형제요소 즉 span
  const target = e.target.nextSibling;

  // 체크여부 확인 후 true일 경우 span에 밑줄, false일 경우 span의 밑줄 없애기
  if (checked) {
    target.style.textDecoration = "line-through";
  } else {
    target.style.textDecoration = "";
  }
};
  • 밑줄 그어지기 원하는 곳은 체크가 된 부분의 형제인 span태그이다.
  • 그러므로 nextSibling을 사용해 주어야 된다.
  • input태그의 checkbox임으로 e.target.checked를 하면 체크여부를 확인할 수 있다.

부모(parent) 노드 탐색

  • parentNode : 부모 노드를 리턴합니다.

자식(child) 노드 탐색

  • childNodes : 자식 노드 목록을 NodeList 형태로 리턴합니다.
  • firstChild : 자식 노드 중, 첫번째 자식 노드를 리턴합니다.
  • lastChild : 자식 노드 중, 마지막 자식 노드를 리턴합니다.

형제(sibling) 노드 탐색

  • previousSibling : 같은 레벨의 노드 중, 이전 노드를 리턴합니다.
  • nextSibling : 같은 레벨의 노드 중, 다음 노드를 리턴합니다.

 

리스트 삭제 기능

// 리스트 추가
const addItem = (text) => {
  if (text) {
    const li = document.createElement("li");
    ...

    span.innerText = text;
    button.innerText = "삭제";

    // 삭제버튼 클릭시 해당 요소의 리스트 삭제
    button.addEventListener("click", delItem);

    // 요소추가
    div.append(checkbox, span);
    li.append(div, button);
    ul.appendChild(li);
  }
};
  • 완료 여부 기능과 마찬가지로 리스트에 추가할 때마다 추가된 리스트에는 리스트 삭제 기능이 작동되어야 되기 때문에 추가 부분에 이벤트 작성
// 리스트 삭제
const delItem = (e) => {
  // 삭제버튼의 부모요소를 찾아오고 그 요소를 삭제해야 된다.
  const target = e.target.parentElement; // 지워야하는 리스트 요소
  target.remove();
};
  • 삭제버튼 클릭 시 li를 삭제해야 되기 때문에 삭제버튼의 부모요소를 찾아와서 그 요소를 삭제해야 된다.
  • remove를 사용하여 해당 요소를 삭제해 준다.

 

참고자료


https://www.youtube.com/watch?v=aV7SCTz5DgM

https://www.youtube.com/watch?v=Dkexm65Ozz0

https://hianna.tistory.com/712

[Javascript] 부모, 자식, 형제 노드(node)와 요소(element) 찾기

지난번에는 node와 element의 차이에 대해서 정리해보았습니다. 이번에는 dom에서 부모, 자식, 형제 노드(node)와 요소(element)를 탐색하는 방법을 정리해 보도록 하겠습니다. node 탐색 부모(parent) 노드

hianna.tistory.com

 

728x90
반응형
Comments