.png)
이제 momentum의 메인 기능인 toDoList를 구현해보도록 하겠습니다.
3가지 동작을 줄 거에요.
천천히 가보죠!!
먼저 HTML을 만져볼게요.
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Momentum</title>
<style>
.form, .greetings {
display: none;
}
.showing {
display: block;
}
</style>
</head>
<body>
<div class="js-clock">
<span>00:00</span>
</div>
<form action="" class="js-form form">
<input type="text" placeholder="What is your name?">
</form>
<h4 class="js-greetings greetings">Hello</h4>
<form action="" class="js-toDoForm">
<input type="text" placeholder="What will you do?">
</form>
<ul class="js-toDoList"></ul>
<script src="clock.js"></script>
<script src="greeting.js"></script>
<script src="todo.js"></script>
</body>
</html>
하나의 form, input, ul 태그를 만들었어요.
form과 input은 greeting때와 유사하게 사용자의 입력을 처리하구요,
ul은 리스트를 위해 넣었습니다. 이 밑에 li 태그들이 하나씩 쌓일거에요.
이제todo.js를 작성해봅시다.
우선 작성한 태그들을 객체화해주고, 사용자의 입력을 기다리는 이벤트 리스너와 로컬 스토리지를 처리하는 부분을 만들어봐요.
toDos[]는 리스트의 정보를 저장할 배열입니다. 객체가 들어갈 거에요.
const toDoForm = document.querySelector(".js-toDoForm");
const toDoInput = toDoForm.querySelector("input");
const toDoList = document.querySelector(".js-toDoList");
const TODOS_LS = "toDo";
let toDos = [];
function init() {
loadToDos();
toDoForm.addEventListener("submit", handleToDoSubmit);
}
init();
loadToDos()는 로컬 스토리지를 이용하니깐 나중에 만들고, handleToDoSubmit() 먼저 구현하겠습니다.
이 친구는 간단해요. 값을 받아서 출력 및 저장 함수에 던져주면 끝이에요.
function handleToDoSubmit(event) {
event.preventDefault();
const currentValue = toDoInput.value;
printToDoValue(currentValue);
event.value = "";
}
printToDoValue()로 가봅시다. 여기서 많은 기능을 구현해야 돼요.
우선 ul 태그 밑에 li를 뿌려줘야 하기 때문에 HTML 태그를 생성해야 합니다.
li 태그 안에는 사용자의 입력을 담는 span 태그와 X 버튼인 button 태그가 필요하겠죠?
javascript에서 태그를 만들 땐 createElement()를 사용합니다.
이 친구들을 어떤 태그의 자식으로 만들 땐 appendChild()를 써요.
코드로 먼저 작상해봅시다.
li 태그들에겐 id값을 1, 2, 3.. 이렇게 줄게요.
function printToDoValue(text) {
const li = document.createElement("li");
const span = document.createElement("span");
const button = document.createElement("button");
span.innerText = text;
button.innerText = "X";
li.appendChild(span);
li.appendChild(button);
const newId = toDos.length + 1;
li.id = newId;
toDoList.appendChild(li);
const toDoObj = {
text: text;
id: newId;
};
toDos.push(toDoObj);
saveToDo();
}
toDos[]에 toDoObj이란 객체를 넣어줬습니다. 얘는 로컬 스토리지에 담길 친구에요.
나중에 불러오기 쉽도록 배열에 저장했습니다.
이제 로컬 스토리지에 직접 저장하는 saveToDo()를 구현할게요.
function saveToDo() {
localStorage.setItem(TODOS_LS, JSON.stringfy(toDos));
}
여기서 JSON.stringfy(toDos)를 사용한 이유는 뭘까요??
콘솔로 직접 찍어서 비교해봅시다.
console.log(toDos);
console.log(JSON.stringfy(toDos));
첫 번째 줄이 일반 객체, 두 번째 줄이 JSON 코드가 적용된 객체입니다.

JSON.stringfy는 자바스크립트의 객체를 string으로 바꿔줍니다.
처음에 로컬 스토리지는 문자열을 저장한다고 했죠??
때문에 저장할 때엔 문자열로, 정보를 긁어와서 자바스크립트에서 사용할 땐 객체로 바꿔주는 작업이 필요해요.
두 번째 줄처럼 문자열로 출력되면 잘 저장된 것입니다.
이제 처음으로 돌아가서, init()에서 작성한 loadToDos()을 구현합시다.
forEach문을 쓸 건데, 얘는 배열 하나하나를 다 돌면서 해당 함수를 실행해요.
아래와 같이 작성하면 로컬 스토리지에 있는 배열 요소(객체) 전체가 함수의 인자로 들어갑니다.
function loadToDos() {
const currentValue = localStorage.getItem(TODOS_LS);
if (currentValue !== null) {
const parseToDos = JSON.parse(currentValue);
parseToDos.forEach(function (todo) {
printToDoValue(todo.text);
}
}
}
지금까지의 결과물이에요.

마지막으로 X 버튼을 누르면 리스트가 사라지는 기능을 구현하겠습니다.
그러기 위해선 먼저 printToDoValue()에 이벤트 리스너를 추가해줘야 해요.
button.addEventListener("click", deleteToDos);
deleteToDos()에선 id값을 기반으로 어떤 리스트의 버튼을 눌렀는지 알아야 합니다.
event.target은 해당 이벤트 발생 시 그 객체를 알려줘요.
위에서 "study JS"를 누르면 그 버튼이 선택되는 것이죠.
우리는 선택된 버튼의 부모 요소인 li의 id값이 필요하잖아요?
target.parent는 타겟의 부모를 알려줘요.
function deleteToDos(event) {
const btn = event.target;
const li = btn.parent;
console.log(btn);
console.log(li);
}
해당 코드의 결과는 아래와 같아요.

드디어 부모 요소까지 접근이 됐습니다!!
이제 이 친구를 지우고 filter()를 사용해 선택된 값을 제외한 새로운 배열을 만들거에요.
요소를 지울 땐 removeChild()를 쓰면 됩니다.
fliter() 안에 함수를 넣으면, forEach 구문처럼 전체 배열을 돌아서 조건에 맞는 친구들끼리 모아 새로운 배열을 만들어요.
function deleteToDos(event) {
const btn = event.target;
const li = btn.parent;
toDoList.removeChild(li);
const cleanToDos = toDos.filter(function (todo) {
return todo.id !== parseInt(li.id);
});
toDos = cleanToDos;
saveTodo();
}
toDos[] 전체를 돌면서 함수를 실행해요.
이 함수는 선택된 li의 id값과 같은 것을 제외한 모든 요소를 cleanToDos 배열에 넣습니다.
parseInt()를 사용한 건 li.id 값이 문자열로 나와서 그런거에요.
이렇게 생성된 배열을 다시 toDos[]에 할당하고 저장합니다.
그러면 완성이에요!!
전체 코드입니다.
const toDoForm = document.querySelector(".js-toDoForm");
const toDoInput = toDoForm.querySelector("input");
const toDoList = document.querySelector(".js-toDoList");
const TODOS_LS = "toDo";
let toDos = [];
function deleteToDos(event) {
const btn = event.target;
const li = btn.parentNode;
toDoList.removeChild(li)
const cleanToDos = toDos.filter(function (todo) {
return todo.id !== parseInt(li.id);
});
toDos = cleanToDos;
saveToDo();
}
function saveToDo() {
localStorage.setItem(TODOS_LS, JSON.stringify(toDos));
}
function printToDoValue(text) {
const li = document.createElement("li");
const span = document.createElement("span");
const button = document.createElement("button");
button.addEventListener("click", deleteToDos);
const newId = toDos.length + 1;
span.innerText = text;
button.innerText = "X";
li.appendChild(span);
li.appendChild(button);
li.id = newId;
toDoList.appendChild(li);
const toDoObj = {
text: text,
id: newId
};
toDos.push(toDoObj);
saveToDo();
}
function handleToDoSubmit(event) {
event.preventDefault();
const currentValue = toDoInput.value;
printToDoValue(currentValue);
toDoInput.value = "";
}
function loadToDos() {
const currentValue = localStorage.getItem(TODOS_LS);
if (currentValue !== null) {
const parseToDos = JSON.parse(currentValue);
parseToDos.forEach(function(todo) {
printToDoValue(todo.text);
});
}
}
function init() {
loadToDos();
toDoForm.addEventListener("submit", handleToDoSubmit);
}
init();
정신없습니다 ㅋㅋㅋㅋㅋㅋㅋ 너무 재밌는데 너무 어렵네요.
외우려고 하지 말고 흐름을 봐야하는데 계속 신경쓰이네요..
더 열심히 하겠습니다. 감사합니다 😊