TO DO LIST 만들기 (1),(2) 에서 부족했던 부분들을 공부하여 수정 후 velog에 올려본다.
TO DO LIST 만들기 (1)
TO DO LIST 만들기 (2)

✍ 내가 만든 TODOLIST (2)에서 부족했던 부분 Check !

  • 브라우저를 새로고침 하게 되면 내가 작성해둔 리스트가 사라진다.

✍ TO DO LIST 만들기 (3)에 추가한 기능 Check !

  • localStorage를 사용하여 브라우저 새로고침을 하게 되어도 내가 작성한 리스트가 계속 화면에 표시되게끔 기능을 구현해주었다. (삭제한 리스트는 새로고침시 보이지않게 코드 작성)

1) '투두리스트 완성하기' 체크 후 "❌" 버튼 클릭하여 해당 리스트 삭제
2) 홈페이지 새로고침시 삭제한 '투두리스트 완성하기' 리스트는 지워지고 'GitHub에 업로드하기'와 
   'Velog 작성하기'만 남는다.

📌 index.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 = () => {
  /* window.onload는 웹 페이지가 로드될 때 실행될 함수를 정의한다. 
  즉, 페이지의 모든 요소가 준비되면 함수 내용이 실행된다.*/
  const toDoWrite = document.querySelector(".todo__write");
  const toDoForm = document.querySelector(".todo-form");
  const mainList = document.querySelector(".main__list");

  let toDos = [];

  function saveToDos() {
    localStorage.setItem("todos", JSON.stringify(toDos));
  }

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

  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.id = newTodo.id;
    const checkBox = document.createElement("input");
    checkBox.setAttribute("type", "checkbox");
    checkBox.addEventListener("change", handleCheckBox);
    const span = document.createElement("span");
    span.innerText = newTodo.text;
    const button = document.createElement("button");
    button.innerText = "❌";
    button.addEventListener("click", deleteToDo);

    li.appendChild(checkBox);
    li.appendChild(span);
    li.appendChild(button);
    mainList.appendChild(li);
  };

  const handleToDoSubmit = (event) => {
    event.preventDefault(); // 폼 제출 기본 동작을 중단시키기
    const newTodo = toDoWrite.value; // newTodo에 입력한 할일을 저장한다.
    toDoWrite.value = ""; /* newTodo에 저장해놨으니 toDoWrite의 value는 다시 ""로 설정하여 
    새로운 목록을 입력받을 준비를 한다. */
    const newTodoObj = {
      text: newTodo,
      id: Date.now(),
    };
    toDos.push(newTodoObj);
    /* 새로운 To-Do 항목을 나타내는 객체(newTodoObj)를 생성하여 toDos 배열에 추가한다.*/
    paintToDo(newTodoObj);
    /* paintToDo() 함수를 호출하여 새로운 To-Do 항목을 화면에 표시한다. */
    saveToDos();
  };

  const savedToDos = localStorage.getItem("todos");

  toDoForm.addEventListener("submit", handleToDoSubmit);
  if (savedToDos !== null) {
    const parsedToDos = JSON.parse(savedToDos);
    toDos = parsedToDos;
    parsedToDos.forEach(paintToDo);
  }
};

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

* 브라우저를 새로고침 하게 되면 내가 작성해둔 리스트가 사라진다.
localStorage를 사용하여 브라우저 새로고침을 하게 되어도 내가 작성한 리스트가 계속 화면에 표시되게끔 
기능을 구현해주었다. (삭제한 리스트는 새로고침시 보이지않게 코드 작성)
  let toDos = []; 
/* 빈 배열 toDos를 선언한다. 이 배열은 사용자가 추가하는 모든 To-Do 항목들을 저장할 배열이다. */

  function saveToDos() {
    localStorage.setItem("todos", JSON.stringify(toDos));
  }
/* 
1. JSON.stringify(toDos)을 통해서 localStorage에 스트링으로 저장되어 
array로 볼수있게 만들어줘야 중복이 가능해진다. 
(toDos 배열을 JSON 형식으로 변환하여 로컬 스토리지에 "todos"라는 키로 저장한다.)
2. saveTodos 함수의 역할은 toDos array의 내용을 localStorage에 넣는다.
*/

  const handleToDoSubmit = (event) => {
    event.preventDefault(); // 폼 제출 기본 동작을 중단시키기
    const newTodo = toDoWrite.value; // newTodo에 입력한 할일을 저장한다.
    toDoWrite.value = ""; /* newTodo에 저장해놨으니 toDoWrite의 value는 다시 ""로 설정하여 
    새로운 목록을 입력받을 준비를 한다. */
    const newTodoObj = {
      text: newTodo,
      id: Date.now(),
    };
    toDos.push(newTodoObj);
    /* 새로운 To-Do 항목을 나타내는 객체(newTodoObj)를 생성하여 toDos 배열에 추가한다.*/
    paintToDo(newTodoObj);
    /* paintToDo() 함수를 호출하여 새로운 To-Do 항목을 화면에 표시한다. */
    saveToDos();
  };

  const savedToDos = localStorage.getItem("todos"); 
/* localStorage에 저장해둔 item들을 가져와서 savedToDos에 저장한다.*/

  if (savedToDos !== null) {
    const parsedToDos = JSON.parse(savedToDos);
    toDos = parsedToDos;
    parsedToDos.forEach(paintToDo);
  }
/* 페이지 로드 후, 이전에 저장된 To-Do 항목을 로컬 스토리지에서 가져온다.
이전에 저장된 항목이 있으면, JSON 형식의 문자열을 파싱하여 parsedToDos 배열로 변환한다.
parsedToDos 배열을 toDos 배열로 설정하고, 각 To-Do 항목을 화면에 표시하기 위해 forEach를 사용하여 
paintToDo() 함수를 호출한다.*/

2개의 댓글

comment-user-thumbnail
2023년 8월 8일

잘 읽었습니다. 좋은 정보 감사드립니다.

1개의 답글
Powered by GraphCDN, the GraphQL CDN