📖 나는 JavaScript를 공부하며 DOM 조작에 있어 가장 자신이 없었으며 미숙했다. 그래서 바닐라JS로 크롬 앱 만들기를 듣게 되었다. 사용자가 입력한 값을 화면에 나타내는 것 뿐만 아니라 localStorage(데이터를 저장할 수 있음)에 저장하고, 삭제하고, 다시 불러오기도 하는 다양한 과정들을 이해할 수 있는 강의였다.
<form id="todo-form">
<input type="text" placeholder="Write a To Do and Press Enter" />
</form>
<ul id="todo-list">
<!-- <li>
<span>사용자가 입력한 to-do 내용</span>
<button>삭제 버튼</button>
</li> -->
</ul>
🛒 To-do 리스트에 필요한 것
- 사용자가 입력할 입력창
form
,input
- 입력할 때마다 입력 내용을 보여줄 리스트
ul
,li
- 입력내용을 삭제할 수 있는 버튼
button
// HTML의 form, input, li 태그를 가져오기
const $toDoForm = document.getElementById("todo-form");
const $toDoInput = toDoForm.querySelector("#todo-form input");
const $toDoList = document.getElementById("todo-list");
// 화면에 to-do 나타내주는 함수
function paintToDo(newTodo) {
const li = document.createElement("li");
const span = document.createElement("span");
li.appendChild(span);
span.innerText = newTodo;
$toDoList.appendChild(li);
}
// input창에 사용가 to-do 입력했을 때
function handleToDoSubmit(event) {
event.preventDefault();
const newTodo = $toDoInput.value;
$toDoInput.value = "";
paintToDo(newTodo);
}
$toDoForm.addEventListener("submit", handleToDoSubmit);
🚚 상세과정
- HTML의
form
,input
,li
태그 가져오기
- 화면에 to-do 나타내기
✔ul
안에 넣을li
와span
태그createElement()
로 생성
✔span
은li
의 자식이므로appendChild()
✔span
에는 사용자가 값을 입력할 때마다 그 입력값을 저장해둔 변수 newTodo를 넣어주기
✔li
는ul
의 자식이므로appendChild()
input
창에 사용가 to-do 입력했을 때
✔ submit 했을 때의 기본동작(새로고침) 방지
✔ 사용자 입력값 변수에 저장 후, 빈칸으로 만들어주기
✔ 사용자 입력값 화면에 그리기
💥 문제점
화면에 입력값이 바로 나타나기는 하나, 새로고침 시 입력값은 모두 없어지고 삭제하고 싶은 입력값을 삭제할 수도 없다. 아래의 2가지를 해결해야 한다.
1. 내가 입력한 to-do 저장해두기 (새로고침해도 남아있음)
2. 내가 입력한 to-do 삭제하기
JSON.stringify()
const player = {name:"nico"};
JSON.stringify(player); // "{\"name\":\"hyerin\"}"
✔ 빈 배열에 사용자가 입력한 입력값을 저장해 localStorage에 저장하고자 한다. 하지만, localStorage는 문자만을 저장할 수 있다.
✔JSON.stringify()
는 JavaScript 객체나 배열, 또는 어떤 JavaScript 코든건 간에 String으로 만들어준다. (값을 String으로 저장시켜주고자 할 때 쓰임)
JSON.parse()
// 처음 localStorage에 갖고 있던 것
localStorage.getItem('todos') // "[\"a\", \"b\", \"c\"]"
// 실제로 무언가를 할 수 있는 배열을 얻을 수 있음
JSON.parse(local.Storage.getItem('todos')) // ["a", "b", "c"]
✔
JSON.parse()
를 통해 문자열로 저장되어 있던 값을 다시 배열로 얻을 수 있다.
JSON.parse()
의 필요성const savedToDos = localStorage.getItem(TODOS_KEY);
console.log(savedToDos);
if (savedToDos !== null) {
const parsedToDos = JSON.parse(savedToDos);
console.log(parsedToDos);
}
✔ savedToDos는 단순한 문자열
["a", "b", "c"]
✔ parse후의 parsedToDos는 배열['a', 'b', 'c']
// const로 변수를 선언하면 toDos가 업데이트 되지 않는다.
const toDos = [];
// let으로 바꾸어 toDos가 업데이트 될 수 있도록 해준다.
let toDos = [];
const savedToDos = localStorage.getItem(TODOS_KEY);
if (savedToDos !== null) {
const parsedToDos = JSON.parse(savedToDos);
// toDos를 파싱해온 ToDos로 업데이트해주기
toDos = parsedToDos;
parsedToDos.forEach(paintToDo);
}
💥 문제점
✔ 새로고침했을 때, 이전에 작성했던 to-do가 사라짐
💡 해결
✔ localStorage에 저장되있는 to-do가 있다면, 파싱해와서 화면에 그려주기
function deleteToDo(event) {
const li = event.target.parentElement;
li.remove();
}
💥 문제점
✔ 화면상에서는 어떤 것을 지워야 할 지 알고 있지만, localStorage에서는 어떤 값을 지워야하는지 알 수 없다. 따라서 화면상의 삭제는 이루어지지만, localStorage 상의 삭제는 되지 않기 때문에 새로고침 시, 삭제한 내용이 반영되지 않는다
💡 해결
✔ 내가 삭제할 to-do가 어떤 것인지 구분할 수 있어야 한다.
✔ 현재 toDos는 배열의 형태로 저장되어 있다. 고유의 id를 주어 object로 만든다면 내가 삭제할 to-do가 무엇인지 구별해낼 수 있다.
const newTodoObj = {
text : newTodo,
id : Date.now();
}
toDos.push(newTodoObj);
paintToDo(newTodoObj);
💾 object 형태로 저장한 to-do
- 이제 빈배열인 toDos에는 to-do내용과 id값이 객체로 저장된다.
function paintToDo(newTodo) {
const li = document.createElement("li");
// id를 추가
li.id = newTodo.id;
const span = document.createElement("span");
// paintToDo는 객체를 받음
span.innerText = newTodo.text;
const button = document.createElement("button");
button.innerText = "❌";
button.addEventListener("click", deleteToDo);
li.appendChild(span);
li.appendChild(button);
toDoList.appendChild(li);
}
🎨 화면에 그려주는 함수 painToDo
- object를 받는 형태로 수정해준다.
function deleteToDo(event) {
// 화면상에서의 삭제
const li = event.target.parentElement;
li.remove();
// localStorage에서의 삭제
toDos = toDos.filter((toDo) => toDo.id !== parseInt(li.id));
// to-do 저장함수
saveToDos();
}
🔥 to-do 삭제 함수
- 화면상에서도 지워주고, 데이터상에서도 지워주어야 한다는 점
- toDos를
filter()
해주는 과정을 통해,li.remove()
되지 않은(삭제되지 않은) to-do들만이 toDos가 될 것toDo.id
는 문자열이고,li.id
는 숫자이므로 이 둘의 타입을 맞춰주어야 함
function saveToDos() {
localStorage.setItem(TODOS_KEY, JSON.stringify(toDos));
}
✨ 문자열로 변환시켜 to-do 저장하는 함수
- 특정 to-do를 지웠다는 것을 localStorage에 반영시켜주어야 하기 때문에, to-do 삭제 함수인
deleteToDo()
에서 데이터를 삭제한 뒤saveToDos()
를 실행시키는 것이다.
쉬지 말고 기록하라.
기억은 흐려지고 생각은 사라진다. 머리를 믿지 말고 손을 믿어라.
<다산 정약용>
📝 공부한 내용을 기록하며 복습하는 과정을 통해 내 것으로 소화시킨 적이 참 많다. 그걸 알면서도 여러 핑계들로 많이 미루기도 미루어왔다. 지금껏 줄곧 알고리즘 문제 풀이를 중점적으로 블로그에 기록해왔다. 나의 기억이 흐려지지 않도록 JavaScript와 React와 같이 현재 공부하고 있는 것들 역시 꾸준히 블로그에 기록해야지.