Roxylife
Roxy 빛나는 새벽
Roxylife
전체 방문자
오늘
어제
  • 분류 전체보기
    • 개발(회고록)현황일기
    • 개발CS지식
    • 알고리즘문제풀기
    • Git
    • 개발언어
      • HTML, CSS
      • JavaScript
    • 프론트엔드
      • React
    • Side Project
      • 혼자Project
      • 팀Project
    • 교육참여
      • [스파르타코딩클럽]
      • [저스트코드]

블로그 메뉴

  • 홈
  • 태그
  • 방명록

공지사항

인기 글

태그

  • 기업협업
  • 신년운세코딩패키지
  • 저스트코드
  • 드림코딩
  • 스파르타코딩클럽후기
  • 팀프로젝트
  • git
  • 스파르타코딩클럽
  • JUSTCODE6기
  • 코딩교육
  • 저스트코드6기
  • JUSTCODE
  • 바닐라JS크롬앱
  • 회고록
  • 스터디코드
  • 힙한취미코딩이벤트
  • JavaScript
  • 개발
  • 노마드코더
  • 코코아톡클론

최근 댓글

최근 글

티스토리

hELLO · Designed By 정상우.
Roxylife

Roxy 빛나는 새벽

To Do List 만들기
개발언어/JavaScript

To Do List 만들기

2021. 9. 3. 15:04

기본 세팅

<form id="todo-form">
      <input type="text" placeholder="Write a To Do and Press Enter" required />
 </form>
 <ul id="todo-list"></ul>
const toDoForm = document.getElementById("todo-form");
const toDoInput = document.querySelector(" #todo-form input");
const toDoList = document.getElementById("todo-list");

function handleToDoSubmit(event) {
  event.preventDefault();
  //   input의 현재 value를 새로운 변수에 복사하는 것.
  const newTodo = toDoInput.value;
  toDoInput.value = "";
}

toDoForm.addEventListener("submit", handleToDoSubmit);

 

ToDo 추가하기

const toDoForm = document.getElementById("todo-form");
const toDoInput = document.querySelector(" #todo-form input");
const toDoList = document.getElementById("todo-list");

// handleToDoSubmit에서 호출한 submit이벤트의 결과를 보여주는 함수.
function paintToDo(newTodo) {
  const li = document.createElement("li");
  const span = document.createElement("span");
  // span을 li의 자식으로 넣고 싶은 코드 / span을 li내부에 집어넣다.
  li.appendChild(span);
  // span의 텍스트는 handleToDoSubmit에서 온 newTodo 텍스트가 되는 것이다. / 텍스트를 span내부에 넣다.
  span.innerText = newTodo;
  // 새로운 li를 toDoList에 추가한다.
  toDoList.appendChild(li);
}

function handleToDoSubmit(event) {
  event.preventDefault();
  // newTodo === input의 value를 비우기 전의 값을 나타내는 string이다.
  const newTodo = toDoInput.value;
  toDoInput.value = "";
  // 그 다음 입력값을 paintToDo에 넣어서 호출하는 것.
  paintToDo(newTodo);
}

toDoForm.addEventListener("submit", handleToDoSubmit);

 

ToDo 삭제하기 (todo삭제하는 버튼만들기)

❌ button 클릭했을 때 li 사라지기

function deleteToDo(event) {
  console.log(event);
}

// handleToDoSubmit에서 호출한 submit이벤트의 결과를 보여주는 함수.
function paintToDo(newTodo) {
  const li = document.createElement("li");
  const span = document.createElement("span");
  // span의 텍스트는 handleToDoSubmit에서 온 newTodo 텍스트가 되는 것이다. / 텍스트를 span내부에 넣다.
  span.innerText = newTodo;
  // Text추가할 때 삭제하는 button 만들기
  const button = document.createElement("button");
  // button텍스트를 X이모지로 대체하기
  button.innerText = "❌";
  // button클릭할 때 eventlistener주기
  button.addEventListener("click", deleteToDo);
  // span, button을 li의 자식으로 넣고 싶은 코드
  li.appendChild(span);
  li.appendChild(button);
  // 새로운 li를 toDoList에 추가한다.
  toDoList.appendChild(li);
}

텍스트를 추가하다보면 클릭이 다 똑같다는 문제점이 발생한다.

자세히 알아보고 싶으면.

console.log(event) 하고 button클릭했을 때 나오는 event들 중에 target: button 이라는 것이 보일 것이다. 

console.log(event.target) 해보면 어떤 button이 클릭되었는지를 알려준다.

console.dir(event.target)해보면 button안을 들여다볼 수 있는데, parentNode / parentElement 보일 것이다..

parentNode / parentElement는 그 button의 부모를 알 수 있다. parentNode: li 우리가 찾던 li이다.

function deleteToDo(event) {
  // target은 클릭된 HTML element이다.
  // parentElemnent 는 클릭된 element의 부모이다.
  console.log(event.target.parentElement);
}
//X라는 이모지 클릭했을 때 li 사라지기
function deleteToDo(event) {
  // target은 클릭된 HTML element이다. target === button 
  // parentElemnent 는 클릭된 element의 부모이다.
  // 우리가 삭제하고 싶은 li이다.
  const li = event.target.parentElement;
  li.remove();
}

// handleToDoSubmit에서 호출한 submit이벤트의 결과를 보여주는 함수.
function paintToDo(newTodo) {
  const li = document.createElement("li");
  const span = document.createElement("span");
  // span의 텍스트는 handleToDoSubmit에서 온 newTodo 텍스트가 되는 것이다. / 텍스트를 span내부에 넣다.
  span.innerText = newTodo;
  // Text추가할 때 삭제하는 button 만들기
  const button = document.createElement("button");
  // button텍스트를 X이모지로 대체하기
  button.innerText = "❌";
  // button클릭할 때 eventlistener주기
  button.addEventListener("click", deleteToDo);
  // span, button을 li의 자식으로 넣고 싶은 코드
  li.appendChild(span);
  li.appendChild(button);
  // 새로운 li를 toDoList에 추가한다.
  toDoList.appendChild(li);
}

 

ToDo 저장하기

// newTodo가 행해질 때마다 그 텍스를 toDos array에 push하고 싶어진다.
const toDos = [];

//toDos array의 내용을 localStorage에 넣는 함수.
function saveToDos() {
  localStorage.setItem("todos", toDos);
}

//X라는 이모지 클릭했을 때 li 사라지기
function deleteToDo(event) {
  // target은 클릭된 HTML element이다. target === button
  // parentElemnent 는 클릭된 element의 부모이다.
  // 우리가 삭제하고 싶은 li이다.
  const li = event.target.parentElement;
  li.remove();
}

// handleToDoSubmit에서 호출한 submit이벤트의 결과를 보여주는 함수.
function paintToDo(newTodo) {
  const li = document.createElement("li");
  const span = document.createElement("span");
  // span의 텍스트는 handleToDoSubmit에서 온 newTodo 텍스트가 되는 것이다. / 텍스트를 span내부에 넣다.
  span.innerText = newTodo;
  // Text추가할 때 삭제하는 button 만들기
  const button = document.createElement("button");
  // button텍스트를 X이모지로 대체하기
  button.innerText = "❌";
  // button클릭할 때 eventlistener주기
  button.addEventListener("click", deleteToDo);
  // span, button을 li의 자식으로 넣고 싶은 코드
  li.appendChild(span);
  li.appendChild(button);
  // 새로운 li를 toDoList에 추가한다.
  toDoList.appendChild(li);
}

function handleToDoSubmit(event) {
  event.preventDefault();
  // newTodo === input의 value를 비우기 전의 값을 나타내는 string이다.
  const newTodo = toDoInput.value;
  // input을 비우고,
  toDoInput.value = "";
  // toDos array를 가지고 와서 newTodo를 toDos array에 push하는 것.
  toDos.push(newTodo);
  // 화면에 toDo를 나타내주고,
  paintToDo(newTodo);
  // toDo들을 저장하기
  saveToDos();
}

// 사용자가 form을 submit하면,
toDoForm.addEventListener("submit", handleToDoSubmit);

단순 텍스트로 저장되는 걸 원치 않기 때문에,

브라우저의 기능 중에 JavaScript object 나 array 나 어떤 것이든 String으로 바꿔주는 기능이 있어야 한다.

▶JSON.stringify()

JSON.stringify를 이용

// newTodo가 행해질 때마다 그 텍스를 toDos array에 push하고 싶어진다.
const toDos = [];

//toDos array의 내용을 localStorage에 넣는 함수.
function saveToDos() {
  localStorage.setItem("todos", JSON.stringify(toDos));
}

 

ToDo 로딩하기

JSON.stringify 와 JSON.parse 의 차이점
단순한 string과 실제로 살아있는 깔끔한 형태의 배열

localStorage.getItem("todos")는 단순한 string     //     

JSON.parse(localStorage.getItem("todos"))는 실제로 살아있는 배열(array)를 얻게 되는 것.

localStorage에서 온 string이 JavaScript에서 사용 가능한 object로 변하게 하는 기능 ▶ JSON.parse()

// toDos Loading하기
const savedToDos = localStorage.getItem(TODOS_KEY);
console.log(savedToDos);
if (savedToDos) {
  // localStorage에서 온 string이 살아있는 JavaScript object로 변하게 하는 것.
  const parsedToDos = JSON.parse(savedToDos);
  console.log(parsedToDos);
}

콘솔창 결과

콘솔창 결과를 보면, array에 있는 각각의 item에 대해 function을 실행하고 싶을 것이다.

▶ forEach() : 화살표 함수

★ ex. parsedToDos.forEach(paintTodo) - 이 paintToDo를 parsedToDos 배열의 요소마다 실행한다. ★

function sayHello(item) {
  console.log("This is the turn of", item);
}

// toDos Loading하기
const savedToDos = localStorage.getItem(TODOS_KEY);
if (savedToDos) {
  // localStorage에서 온 string이 살아있는 JavaScript object로 변하게 하는 것.
  const parsedToDos = JSON.parse(savedToDos);
  console.log(parsedToDos);
  // forEach는 array의 각 item에 대해 function을 실행하게 해주는 역할.
  parsedToDos.forEach(sayHello);
}

콘솔창에서 엿볼 수 있는 forEach의 역할.

//방법 1.
function sayHello(item) {
  console.log("this is the turn of ", item);
} 

parsedToDos.forEach(sayHello);

//방법2.
parsedToDos.forEach((item) => console.log("this is the turn of ", item));
// toDos Loading하기
const savedToDos = localStorage.getItem(TODOS_KEY);
if (savedToDos) {
  // localStorage에서 온 string이 살아있는 JavaScript object로 변하게 하는 것.
  const parsedToDos = JSON.parse(savedToDos);
  // forEach는 array의 각 item에 대해 function을 실행하게 해주는 역할.
  // 각각 item을 화면에 그려주고 싶다.
  parsedToDos.forEach(paintToDo);
}

이 상태에서 새로고침하고 item을 추가하고 localStorage창을 보면 이전의 저장되어있던 array들은 사라지고 추가한 array만 보일 것이다. 왜냐하면, 원래 const toDos = []; 빈값으로 해놨기 때문에......

▶ 이전의 저장되어있던 array들과 추가되는 array들도 함께 나타내는 방법!!!

// toDos 는 항상 빈 array로 시작한다.
// 이전 newTodo 와 계속 추가되는 newTodo를 유지하고 싶기 때문에 const => let
let toDos = [];



// toDos Loading하기
const savedToDos = localStorage.getItem(TODOS_KEY);
if (savedToDos) {
  // localStorage에서 온 string이 살아있는 JavaScript object로 변하게 하는 것.
  const parsedToDos = JSON.parse(savedToDos);
  // toDos에 parsedToDos를 넣어서 전에 있던 toDo들을 복원할 것임. 이전의 toDos 사라지기 않기 위해.
  toDos = parsedToDos;
  // forEach는 array의 각 item에 대해 function을 실행하게 해주는 역할.
  // item을 화면에 그려주고 싶다.
  parsedToDos.forEach(paintToDo);
}

 

이렇게 되면, 또 삭제하는 button을 클릭했지만, 새로고침해도 다시 원래 저장되던 상태로 되돌아간다.라는 문제점!

 

ToDo 삭제하기

toDos array (데이터베이스) ≠ local Storage (toDos array를 복사해두는 곳.)

Step 1. application에 있는 데이터베이스를 지운다.

Step 2. 랜덤으로 ID를 만드는 방법. 마치 Date.now()처럼.... 

▶ 데이터베이스에게 id를 저장하는 옵션

// handleToDoSubmit에서 호출한 submit이벤트의 결과를 보여주는 함수.
// paintToDo는 text를 받았던 함수였다.
// 이제는 object로 받아야 하는 상태.
function paintToDo(newTodo) {
  const li = document.createElement("li");
  // id로 각각의 item을 구별하고 싶다.
  li.id = newTodo.id;
  const span = document.createElement("span");
  // span의 텍스트는 handleToDoSubmit에서 온 newTodo 텍스트가 되는 것이다. / 텍스트를 span내부에 넣다.
  // text로 받았던 걸 object로 받아야 하기 때문에 newTodo.text로 고친다.
  span.innerText = newTodo.text;
  // Text추가할 때 삭제하는 button 만들기
  const button = document.createElement("button");
  // button텍스트를 X이모지로 대체하기
  button.innerText = "❌";
  // button클릭할 때 eventlistener주기
  button.addEventListener("click", deleteToDo);
  // span, button을 li의 자식으로 넣고 싶은 코드
  li.appendChild(span);
  li.appendChild(button);
  // 새로운 li를 toDoList에 추가한다.
  toDoList.appendChild(li);
}

function handleToDoSubmit(event) {
  event.preventDefault();
  // newTodo === input의 value를 비우기 전의 값을 나타내는 string이다.
  const newTodo = toDoInput.value;
  // input을 비우고,
  toDoInput.value = "";
  // text 대신 object를 push한다.
  const newTodoObj = {
    text: newTodo,
    id: Date.now(),
  };
  // toDos array를 가지고 와서 newTodo를 toDos array에 push하는 것.
  // 데이터베이스로 매번 사용자가 적어둔 text를 push한다.
  // toDos 배열에 newTodoObj추가하게 된다.
  toDos.push(newTodoObj);
  // 화면에 toDo를 나타내주고,
  // paintToDo에는 text 대신 object로 변하고 싶어 newTodoObj추가하게 된다.
  paintToDo(newTodoObj);
  // toDo들을 저장하기
  saveToDos();
}

 

Step 3.

▶ array에서 item을 지우는 법

▶ 지우고 싶은 item을 제외하고 새 array를 만드는 일 ▶ filter() - 선택옵션 / forEach()와 비슷하다.

★ 새 array에 item을 유지하고 싶으면 true를 리턴해야 한다.

Filter() 함수의 역할
sexyFilter true
sexyFilter false
예시 1. item이 3인 것을 제외하기
예시 2. banana인 것을 제외하기
예시 3. 1000보다 작거나 같은 것을 제외하기
예시 4. todo.id 해당 id인 것을 제외하기
예시 5. todo.text 해당text인 것을 제외하기
앞에 나온 sexyFilter함수선언없이 만들 수 있는 형태.

//X라는 이모지 클릭했을 때 li 사라지기
function deleteToDo(event) {
  // target은 클릭된 HTML element이다. target === button
  // parentElemnent 는 클릭된 element의 부모이다.
  // 우리가 삭제하고 싶은 li이다.
  const li = event.target.parentElement;
  li.remove();
  // 클릭했던 li의 id를 갖고 있는 toDo를 지우고 싶다.
  // toDo의 id가 li의 id와 다른 걸로 남기고 싶다. 
  toDos = toDos.filter((toDo) => toDo.id !== li.id);
}

이 상태에서 localStorage 빈 곳을 삭제하고 다시 입력하면, 삭제하는 button클릭해도 콘솔창에는 button클릭 안한 것과 같은 결과가 나온다. 왜냐하면, id는 number이기 때문에.....

즉, li.id는 string타입이다. toDo.id는 number타입이다.

//toDos array의 내용을 localStorage에 넣는 함수.
// JSON.stringify === toDos를 string으로 바꾸는 형태.
function saveToDos() {
  localStorage.setItem(TODOS_KEY, JSON.stringify(toDos));
}

//X라는 이모지 클릭했을 때 li 사라지기
function deleteToDo(event) {
  // target은 클릭된 HTML element이다. target === button
  // parentElemnent 는 클릭된 element의 부모이다.
  // 우리가 삭제하고 싶은 li이다.
  const li = event.target.parentElement;
  li.remove();
  // 클릭했던 li의 id를 갖고 있는 toDo를 지우고 싶다.
  // toDo의 id가 li의 id와 다른 걸로 남기고 싶다.
  // li.id == string타입 / toDo.id == number타입
  // 그래서 parseInt 이용해서 문자열로 바꿔준다.
  // toDos DB에서 todo를 지운 뒤에
  toDos = toDos.filter((toDo) => toDo.id !== parseInt(li.id));
  // saveToDos를 한 번 더 부른다.
  saveToDos();
}

 

 

최종적 코드

const toDoForm = document.getElementById("todo-form");
const toDoInput = document.querySelector(" #todo-form input");
const toDoList = document.getElementById("todo-list");

const TODOS_KEY = "todos";

// newTodo가 행해질 때마다 그 텍스를 toDos array에 push하고 싶어진다.
// toDos 는 항상 빈 array로 시작한다.
// 이전 newTodo 와 계속 추가되는 newTodo를 유지하고 싶기 때문에 const => let
// 데이터베이스에 ToDo내용을 추가하는 곳.
let toDos = [];

//toDos array의 내용을 localStorage에 넣는 함수.
// JSON.stringify === toDos를 string으로 바꾸는 형태.
function saveToDos() {
  localStorage.setItem(TODOS_KEY, JSON.stringify(toDos));
}

//X라는 이모지 클릭했을 때 li 사라지기
function deleteToDo(event) {
  // target은 클릭된 HTML element이다. target === button
  // parentElemnent 는 클릭된 element의 부모이다.
  // 우리가 삭제하고 싶은 li이다.
  const li = event.target.parentElement;
  li.remove();
  // 클릭했던 li의 id를 갖고 있는 toDo를 지우고 싶다.
  // toDo의 id가 li의 id와 다른 걸로 남기고 싶다.
  // li.id == string타입 / toDo.id == number타입
  // 그래서 parseInt 이용해서 문자열로 바꿔준다.
  // toDos DB에서 todo를 지운 뒤에
  toDos = toDos.filter((toDo) => toDo.id !== parseInt(li.id));
  // saveToDos를 한 번 더 부른다.
  saveToDos();
}

// handleToDoSubmit에서 호출한 submit이벤트의 결과를 보여주는 함수.
// paintToDo는 text를 받았던 함수였다.
// 이제는 object로 받아야 하는 상태.
function paintToDo(newTodo) {
  const li = document.createElement("li");
  // id로 각각의 item을 구별하고 싶다.
  li.id = newTodo.id;
  const span = document.createElement("span");
  // span의 텍스트는 handleToDoSubmit에서 온 newTodo 텍스트가 되는 것이다. / 텍스트를 span내부에 넣다.
  // text로 받았던 걸 object로 받아야 하기 때문에 newTodo.text로 고친다.
  span.innerText = newTodo.text;
  // Text추가할 때 삭제하는 button 만들기
  const button = document.createElement("button");
  // button텍스트를 X이모지로 대체하기
  button.innerText = "❌";
  // button클릭할 때 eventlistener주기
  button.addEventListener("click", deleteToDo);
  // span, button을 li의 자식으로 넣고 싶은 코드
  li.appendChild(span);
  li.appendChild(button);
  // 새로운 li를 toDoList에 추가한다.
  toDoList.appendChild(li);
}

function handleToDoSubmit(event) {
  event.preventDefault();
  // newTodo === input의 value를 비우기 전의 값을 나타내는 string이다.
  const newTodo = toDoInput.value;
  // input을 비우고,
  toDoInput.value = "";
  // text 대신 object를 push한다.
  const newTodoObj = {
    text: newTodo,
    id: Date.now(),
  };
  // toDos array를 가지고 와서 newTodo를 toDos array에 push하는 것.
  // 데이터베이스로 매번 사용자가 적어둔 text를 push한다.
  // toDos 배열에 newTodoObj추가하게 된다.
  toDos.push(newTodoObj);
  // 화면에 toDo를 나타내주고,
  // paintToDo에는 text 대신 object로 변하고 싶어 newTodoObj추가하게 된다.
  paintToDo(newTodoObj);
  // toDo들을 저장하기
  saveToDos();
}

// 사용자가 form을 submit하면,
toDoForm.addEventListener("submit", handleToDoSubmit);

// toDos Loading하기
const savedToDos = localStorage.getItem(TODOS_KEY);
if (savedToDos !== null) {
  // localStorage에서 온 string이 살아있는 JavaScript object로 변하게 하는 것.
  // JSON.parse === toDos 살아있는 array가 된 형태.
  const parsedToDos = JSON.parse(savedToDos);
  // toDos에 parsedToDos를 넣어서 전에 있던 toDo들을 복원할 것임. 이전의 toDos 사라지기 않기 위해.
  toDos = parsedToDos;
  // forEach는 array의 각 item에 대해 function을 실행하게 해주는 역할.
  // item을 화면에 그려주고 싶다.
  // forEach함수는 이 paintToDo를 parsedToDos 배열의 요소마다 실행한다.
  parsedToDos.forEach(paintToDo);
}

'개발언어 > JavaScript' 카테고리의 다른 글

[JavaScript] 데이터 타입 Data Types 의 종류  (0) 2022.07.27
Weather날씨 만들기  (0) 2021.09.04
Quotes and Background 명언 만들기  (0) 2021.09.02
Clock만들기  (0) 2021.09.01
Login만들기  (0) 2021.09.01
    '개발언어/JavaScript' 카테고리의 다른 글
    • [JavaScript] 데이터 타입 Data Types 의 종류
    • Weather날씨 만들기
    • Quotes and Background 명언 만들기
    • Clock만들기
    Roxylife
    Roxylife
    꿈나무 FE개발자

    티스토리툴바