IT/개발

#7 [2021 UPDATE] TO DO LIST / createElement()함수 / appendChild() 함수 / target.parentElement / 화살표함수 / filter() 함수

공장장J 2022. 4. 4. 00:14
반응형

7.0 todo list 만들기

<index.html>
15~18번, 28번 라인을 추가작성한다.
15~18번열 - todo 입력 폼 안에 input 태그 있음.
28번열 - 입력받은 todo 값을 리스트로 나열할 ul  태그

 

<todo.js>
toDoForm 이 제출submit 될 때 브라우저가 기본 동작으로 새로고침 되는 것을 막기 위해 
preventDefault() 함수를 사용한다.

newTodo 라는 변수를 만들어 toDoInput에서 입력받은 값을 저장한다.
입력 후 input 창이 비워져야 또 값을 입력할 수 있기 때문에 
toDoInput.value = ""; 하여 input창에 입력된 값을 지워준다.

 

7.1

화면에 표출시키기 위한 painToDo() 함수를 만들어준다.
html의 엘리먼트를 javascript에서 만들어준다. 입력받은 값의 갯수에 따라 리스트가 추가되므로 javascript에서 만든다.
javascript에서 html 엘리먼트를 추가하려면 createElement() 함수를 사용하면 된다.

createElement()함수
const 변수명 = document.createElement("엘리먼트명");
생성할 엘리먼트와 헷갈리지 않게 변수명도 동일하게 지어주자. 물론 변수명이기 때문에 자기 맘데로 지어도 된다.

appendChild()함수
li와 span을 생성하고 span을 li 안에 넣어준다. 
li.appendChild(span);

 

7.2 삭제버튼생성 후 삭제기능 부여하기

todo를 삭제하는 버튼 추가
14번열 const button = document.createElement("button");
자바스크립트 내부에서 버튼 엘리먼트를 생성하고
15번열 button.innerText = "X";
생성된 버튼에 X 모양을 추가한다.
버튼이 클릭되고 삭제되는 이벤트를 수행하는 걸 인지시키기 위해
16번열 button.addEventListener("click", 삭제함수명); 을 추가한다.

todo 삭제 버튼에 삭제 기능 추가하기
버튼의 삭제 기능을 수행할 함수
function deleteTodo(event) {} 를 생성한다. 함수명은 deleteTodo
target은 클릭된 HTML element.
target.parentElement는 타겟의 부모 엘리먼트를 의미.
여기서 target은 버튼이고 버튼은 li 안에 위치하므로 부모 엘리먼트는 li다.
const 변수명 = event.target.parentElement; 는 li를  가르킨다.
li를 변수명 li에 저장한 후 remove()함수를 사용해 삭제하면 된다.
변수명.remove();

 

7.3 ToDos 저장하기 (헷갈림, 이해필요) 

input창으로 입력받은 todo list 들을 localStorage에 저장하는 방법이다.
지금까지는 입력을 받으면 화면에 표출되었지만 저장소에 저장이 되어있지 않았다.
로컬 스토리지에 저장받기 위해 입력값을 모아둘
const toDos = []; 라는 배열을 만들어준다.

다음 그 배열을 로컬 스토리지에 저장할 함수를 만든다.
function saveTodos() { localStorage.setItem("todos", toDos); }
여기서 괄호 안 "todos"는 키고, toDos는 배열 값이다.

localStorage에 toDos를 그냥 저장했을 때

toDos는 배열임에도 localStorage에 아래와 같이 값이 string으로 저장이 된다.

 

 

위에서 toDos Array 배열을 로컬스토리지에 저장했으나 문제는 로컬스토리지는 오직 text (즉 string) 만 저장한다. 따라서 배열은 저장할 수 없음
그래서 사용하는 것이 JSON.stringify() 다. toDos Array를 string으로 변환하여 저장할 수 있게 한다.
예를 들어 ["가", "나"] 배열을 "["가", "나"]" string으로 변형하는 것이다.

 

29번열 - 입력하고 엔터를 누르면(이벤트) submit하면 브라우저가 새로고침 되는 것을 막고
30번열 - newTodo라는 변수에 입력받은 todo 값을 저장한다.
31번열 - 입력받은 todo 값은 새 변수에 저장했으므로 입력받은 todo 값은 비워준다.
32번열 - newTodo 로 옮겨진 todo값을 toDos 라는 배열로 보낸다.
33번열 - paintTodo 함수를 이용해 newTodo 를 화면에 표출한다.

* 32번열 원래 const로 변수를 생성하면 나중에 값을 업데이트 할 수 없지만 배열이나 객체는 const 로 선언해도 내부의 값을 추가할 수 있다. 배열이나 객체도 원래 있던 값을 변경하는 것은 아니고 추가가 가능한 것.

 

localStorage에 배열처럼 저장된 todo값들을 Application에서 확인할 수 있다. 
키는 todos 값은 []

 

7.4 Local Storage에 저장했으나 새로고침 하면 여전히 브라우저에서 사라지는 문제 해결

JSON.stringify()
를 사용하면 배열도(객체도) string으로 변경한다.

앞 7.3의 내용까지 정리하자면 로컬스토리지에 배열을 저장하고 싶으나 로컬스토리지는 모든 것을 스트링으로 저장한다.
따라서 배열 자체를 스트링으로 변경하는 JSON.stringify() 를 사용하면 배열 [1, 2, 3, 4] 가 "[1, 2, 3, 4]" 라는 스트링으로 변경된다.
즉 배열처럼 생긴  String으로 저장했다가  JSON.parse() 를 사용하여 배열로 다시 변경하는 것이다.

JSON.parse()
를 사용하면 javascript가 이해할 수 있는 배열로 변경해준다.

 

 

 

forEach는 array의 각 아이템에 대해 function을 실행하게 한다.

화살표 함수를 사용하면 함수 이름도 필요없이 한줄로 간단히 작성할 수 있다. 아래와 위의 코드는 동일한 실행을 하지만 길이는 아래 화살표 함수를 사용해서 더 짧고 간단하다. (sayHello() 라는 이름의 함수가 필요없어짐)

 

7.5

이전값들이 저장되지 않고 새로운 값들에 덮어씌워지는 이유는 application이 시작될 때 toDos array 는 항상 비어있기 때문이다.

const toDos = [];

이 코드 때문. 이 문제를 고치는 방법은 매우 간단하다.
7번열 - const 를 업데이트 가능한 let으로 변경하고
45번열 - 만약 savedToDos 가 있다면 toDos는 parsedToDos가 된다.

 

7.6 삭제-1

새로운 문제! todo옆 삭제버튼을 누르면 화면에서는 삭제되지만 로컬스토리지에는 그대로 남아있다.
로컬스토리지까지 제대로 지우는 방법에 대한 내용이다.

이문제를 해결하기 위해 입력되는 텍스트들에게 아이디를 부여한다.
Date.now()를 사용해 현재시간을 아이디로 사용하면 랜덤한 숫자와 같은 효과를 줄 수 있다.

34~37번열 - 텍스트만 존재하던 배열안의 문자열들을 id를 갖은 객체로 변경한다.

painToDo 함수에서 li.id = newTodo.id라고 선언
브라우저에 text만 표출하기 위해서 newTodo.text;로 변경해준다.

 

 7.7 삭제 -2 (filter 함수)

삭제할 때 실제로는 이전 배열은 그대로 있고 삭제하고 싶은 item을 제외시키고 새 배열을 만들어 내는 것이다.
filter 함수를 사용하면 된다. filter 함수를 사용하려면 filter함수에 사용할 함수를 만들어야한다.
filter 사용할 때 true를 반환해야 새로운 배열에 유지된다. false를 반환하면 그 아이템은 새 배열에 제외가 된다.
filter 는 forEach 함수와 비슷하다. 배열 안에 있는 아이템들에 함수가 차례대로 실행된다.

 

 

7.8 삭제-3

물론 아래와 같이 filter함수가 사용할 조건을 담은 함수를 만들지 않고 filter함수 내에 화살표 함수로 작성할 수 있다.

filter를 했지만 arr를 불렀을 때 그대로 남아있는 것을 보면
삭제되는 것이 아니라 새 배열로 교체되는 것을 알 수 있다.


<todo.js>
14번열 - 선택된 것의 부모엘리먼트를 li 변수에 저장. 부모엘리먼트는 li들 중 하나일테니까 변수명도 li로 지음
15번열 - remove() 함수를 사용해 화면에서 li (즉 선택된 부모엘리먼트)를 지워버림 (7.2 참고)
16번열 - toDo.id가 숫자이고 li.id는 string이기 때문에 parseInt(li.id)하여 string을 숫자로 바꿔줘야 작동한다.
toDos 배열에 들어있는 아이템의 아이디는 선택한 아이템(li.id)와 같지 않으면 새 배열에 남긴다. 같으면 제외시킨다.
17번열 - 로컬스토리지에 저장하는 함수 실행.

*li.id는 Date.now() 함수를 사용해 시간 숫자로 받은 것인데 왜 데이터타입이 string이 나오는 걸까???
답 - li.id = newTodo.id; 라는 부분 때문이다. li는 DOM의 일부인데 아무리 아이디를 숫자로 넣었어도 DOM의 id는 문자열이 된다. mdn문서 설명!

 

반응형