[Javascript] TO DO LIST 만들기 (2)

은비·2023년 7월 19일
1

JS_Project

목록 보기
2/8
post-thumbnail

TO DO LIST 만들기 (1) 에서 부족했던 부분들을 공부하여 수정 후 velog에 올려본다.
처음 내가 만든 TODOLIST

✍ 부족했던 부분 Check !

  • 할 일 작성 후 Enter를 눌렀을때 리스트에 추가되게끔 기능을 구현하고 싶었는데 못하였다.
  • 할 일을 작성하여 추가하면 리스트가 여러 개 생성되는 게 아니라 계속 리스트가 새로고침 되어 전에 작성했던 리스트가 없어진다.

✍ 추가하고 싶은 기능 Check !

  • 할 일 완료시 체크박스에 체크를 해주면 선을 그어준다.
  • ❌ 버튼을 누르게 되면 해당 할 일을 삭제해준다.
이번에 공부하면서 Html에서는 Header, main, footer 태그를 사용하여 웹 페이지를 구성하는 것이 
<div>를 사용하는 것보다 선호된다는 것을 알게되어 이번에 다시 코드 작성하면서 조금 변경해주었다.

* Header, main, footer 태그들이 더 선호되는 이유 3가지 정리
1. Header, main, footer는 HTML5에서 추가된 시맨틱 태그로서, 문서의 구조를 더 의미론적으로 설명한다. 
이러한 태그를 사용하면 웹 페이지의 각 부분이 무엇을 의미하는지 쉽게 이해할 수 있다. 
즉, 코드를 읽는 사람과 검색 엔진에게 해당 컨텐츠의 의미를 명확하게 전달할 수 있다.
2. 시맨틱 태그를 사용하면 웹 접근성이 향상된다. 스크린 리더나 다른 보조 기술을 사용하는
사용자들이 웹 페이지를 더 잘 이해하고 탐색할 수 있다. 
특히 header 태그는 웹 페이지의 제목이나 로고 등 중요한 정보를 제공하는 데 사용된다.
3. 시맨틱 태그를 사용하면 웹 페이지의 구조가 더 명확해지기 때문에 코드를 읽고 이해하기 쉽다. 
따라서 코드를 유지보수하거나 다른 개발자와 협업할 때 더 편리하다.

📌 todo.html

<!DOCTYPE html>
<html lang="ko">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>TO DO LIST</title>
    <script src="./todo.js"></script>
    <link rel="stylesheet" href="./todo.css" />
  </head>
  <body>
    <div class="wrapper">
      <header>TO DO LIST</header>
      <main>
        <div class="wrapper__main">
          <form class="todo-form">
            <input
              class="todo__write"
              type="text"
              placeholder="할 일을 작성 후 Enter를 눌러주세요~!!"
              required
            />
			<!-- required 속성은 form의 요소로 필드에 값을 입력하지 않으면 폼이 제출되지 않는다. 
			즉, 브라우저가 자동으로 해당 필드가 비어있는지 확인하고, 필드가 비어있다면 폼의 제출을 막아 
			사용자에게 해당 필드를 채우도록 유도한다. -->
          </form>
          <div class="wrapper__main__list">
            <ul class="main__list"></ul>
          </div>
        </div>
      </main>
      <footer>
        <div class="wrapper__footer">
          <div class="writer">Writer : kwon Eunbi</div>
        </div>
      </footer>
    </div>
  </body>
</html>

📌 todo.css

* {
  box-sizing: border-box;
}

body {
  width: 100%;
  height: 100vh; 
  // 높이를 px로 지정하게되면 리스트가 계속 추가될시 화면을 넘을수있다. 그래서 vh로 설정해두었다.
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
}

.wrapper {
  width: 70%;
  background-color: hwb(180 82% 7%);
  padding: 20px 30px;
  border: 3px solid black;
  border-radius: 15px;
}

header {
  font-size: 60px;
  font-weight: 800;
  text-align: center;
}

main {
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
}

.wrapper__main {
  display: flex;
  flex-direction: column;
}

.todo-form {
  display: flex;
  justify-content: center;
  align-items: center;
}

.todo__write {
  text-align: center;
  font-size: 25px;
  margin-right: 10px;
}

.todo__write::placeholder {
  font-size: 16px;
  font-style: oblique;
  text-align: center;
}

.wrapper__main__list {
  display: flex;
  justify-content: center;
  align-items: stretch;
  font-size: 23px;
  width: 100%;
}

.main__list {
  width: 100%;
  padding: 0;
}

ul {
  width: 100%;
  list-style: none;
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
}

li {
  width: 100%;
  display: flex;
  flex-direction: row;
  justify-content: space-between;
}

span {
  margin: 0px 10px 0px 10px;
  font-size: 16px;
  font-style: unset;
}

.writer {
  font-weight: 600;
  font-size: 18px;
  word-wrap: normal;
  text-align: center;
}

📌 todo.js

window.onload = () => {
  const toDoWrite = document.querySelector(".todo__write");
  const toDoForm = document.querySelector(".todo-form");
  const mainList = document.querySelector(".main__list");

  const deleteToDo = (event) => {
    const li = event.target.parentElement;
    // JavaScript에서 사용되는 속성으로, 이벤트 핸들러 내에서 이벤트가 발생한 요소의 부모 요소를 나타낸다.
    li.remove();
  };

  const handleCheckBox = (event) => {
    const li = event.target.parentElement;
    const span = li.querySelector("span");
    span.style.textDecoration = event.target.checked ? "line-through" : "none";
    /* target.checked는 이벤트가 발생한 요소의 체크 여부를 나타내는 속성이다.
    이벤트 핸들러 내에서 event.target은 이벤트가 발생한 요소를 참조한다.
    체크박스의 경우, target.checked는 체크박스가 선택되어 있는지 여부를 나타내는 불리언 값이다.
    선택되어 있을 경우 true를 반환하고, 선택되어 있지 않을 경우 false를 반환한다. */
  };

  const paintToDo = (newTodo) => {
    const li = document.createElement("li"); // li 태그 만들기
    const checkBox = document.createElement("input"); // input 태그 만들기
    checkBox.setAttribute("type", "checkbox"); // input 태그의 type="checkbox"로 설정하기
    checkBox.addEventListener("change", handleCheckBox); /* 체크박스의 체크 여부가 변경되었을 때 
    change 이벤트가 호출 , handleCheckBox 함수 실행시키기 */
    const span = document.createElement("span"); // span 태그 만들기
    span.innerText = newTodo; // span 태그의 텍스트를 매개변수로 받은 newTodo를 넣기
    const button = document.createElement("button"); // 버튼 태그 만들기
    button.innerText = "❌"; // 버튼 태그의 텍스트를 "❌"로 넣기
    button.addEventListener("click", deleteToDo); 
    // 버튼 클릭시 이벤트 호출, deleteToDo 함수 실행시키기

    li.appendChild(checkBox); // li의 자식요소로 checkBox 넣기
    li.appendChild(span); // li의 자식요소로 span 넣기
    li.appendChild(button);  // li의 자식요소로 button 넣기
    mainList.appendChild(li);  // mainList의 자식요소로 li 넣기
  };

  const handleToDoSubmit = (event) => {
    event.preventDefault(); // 폼 제출 기본 동작을 중단시키기
    const newTodo = toDoWrite.value; // newTodo에 입력한 할일을 저장한다.
    toDoWrite.value = ""; /* newTodo에 저장해놨으니 toDoWrite의 value는 다시 ""로 설정하여 
    새로운 목록을 입력받을 준비를 한다. */
    paintToDo(newTodo);
  };

  toDoForm.addEventListener("submit", handleToDoSubmit);
};

✍ 수정 사항 (부족한 부분 개선)

1. 할 일 작성 후 Enter를 눌렀을때 리스트에 추가되게끔 기능 구현하기
Enter를 눌렀을때 리스트에 추가되게끔 기능을 구현하기 위해 먼저 input을 <form>으로 감싸주었다. 
원래는 <form> 안에서 엔터(Enter)를 누를 경우 기본 동작은 폼을 서버로 제출하고 페이지를 새로고침한다. 
내가 원하는 기능은 새로고침이 아닌 리스트에 추가되는 것이기 때문에 기본동을 하지않게 막아주는 
preventDefault()를 사용하여 폼 제출 기본 동작을 중단시키고 이후 작업을 실행 시켜주었다.
2. 할 일을 추가하면 리스트에 추가한 만큼 화면에 보이게 기능 구현하기
javascript에서 createElement를 이용해서 li태그를 만들어주고 html에 미리 만들어놓은 ul태그에 
appendChild를 이용하여 자식요소로 지정해준다. 자세한 내용은 위에 코드를 보면 알수있다.
3. 할 일 완료시 체크박스에 체크를 해주면 선을 그어준다.
const handleCheckBox = (event) => {
    const li = event.target.parentElement;
    /* target.parentElement은 JavaScript에서 사용되는 속성으로, 
  이벤트 핸들러 내에서 이벤트가 발생한 요소의 부모 요소를 나타낸다. */
    const span = li.querySelector("span");
    span.style.textDecoration = event.target.checked ? "line-through" : "none";
    /* target.checked는 이벤트가 발생한 요소의 체크 여부를 나타내는 속성이다.
    이벤트 핸들러 내에서 event.target은 이벤트가 발생한 요소를 참조한다.
    체크박스의 경우, target.checked는 체크박스가 선택되어 있는지 여부를 나타내는 불리언 값이다.
    선택되어 있을 경우 true를 반환하고, 선택되어 있지 않을 경우 false를 반환한다. */
  };
4. * ❌ 버튼을 누르게 되면 해당 할 일을 삭제해준다.
const deleteToDo = (event) => {
    const li = event.target.parentElement;
    /* target.parentElement은 JavaScript에서 사용되는 속성으로, 
  이벤트 핸들러 내에서 이벤트가 발생한 요소의 부모 요소를 나타낸다. */
    li.remove(); // 해당 부모요소인 li를 remoeve(제거)시킴
  };

🧐 코드 작성하면서 막혔던 부분?!

열심히 javascript 코드를 작성하고 있는데 이유모를 오류가 발생되었다,,

addEventListener를 읽어올 수 없다는 오류가 떠있는데 코드는 아무리 봐도 잘 작성했는데
무엇이 문제인지 머리를 싸매다가 갑자기 떠오른 게 window.onload였다.
javascript 코드 전체 블록을 window.onload 함수로 감싸니까 오류가 없어졌다!!!
이참에 window.onload에 대해 더 자세히 공부해 보았다.

window.onload 이벤트는 HTML 문서의 로드 완료 후에 실행되는 JavaScript 코드를 정의하는 데 사용된다.
일반적으로 JavaScript 코드는 HTML 문서의 특정 요소를 조작하거나, 이벤트 핸들러를 등록하거나, 
초기화 작업을 수행하는 등의 작업을 수행한다. 이러한 작업은 HTML 문서의 로드가 완료된 후에 이루어져야 한다. 
따라서 window.onload 이벤트를 사용하여 페이지 로드 완료 후에 JavaScript 코드를 실행하도록 
구성하는 것이 중요하다. 만약 window.onload 없이 JavaScript 코드를 작성하면, 
코드가 HTML 문서가 로드되기 전에 실행될 수 있다. 
예를 들어, JavaScript 코드가 DOM 요소를 조작하려고 할 때 해당 요소가 아직 로드되지 않았다면 
오류가 발생할 수 있다. window.onload 이벤트를 사용하면 HTML 문서의 로드가 완료된 후에 
JavaScript 코드가 실행되므로 이러한 오류를 방지할 수 있다. 따라서 window.onload를 사용하여 
JavaScript 코드를 감싸면, HTML 문서의 로드 완료 후에 JavaScript 코드가 실행되므로 
오류가 발생할 가능성이 줄어든다.

velog에 정리하면서 내가 작성한 코드를 한번 더 보게 되고 더 추가 하고 싶거나 아쉬운 기능들이 보여서 한번더 만들어보려고 한다.

0개의 댓글