이제 To-Do-List를 구현해보자.
학습 날짜 : 23.08.11
To-Do-List를 구현하려면 먼저 form이 필요하다. 그리고 리스트를 만들어준다. 이때 ul 태그만 HTML로 작성하고 자바스크립트로 li를 추가할 것이다.
<form id="todo-form">
<input type="text" placeholder="할일을 작성하고 눌러주세요.">
</form>
<ul id="todo-list"></ul>
form은 기본적으로 submit 이벤트를 갖고 있다. 함수를 만들고 그 이벤트의 기본 동작인 submit를 막을 것이다.
const toDoForm = document.getElementById("todo-form");
const toDoList = document.getElementById("todo-list");
function handleToDoSubmit(event){
event.preventDefault();
}
toDoForm.addEventListener("submit", handleToDoSubmit);
input의 value 값을 얻고, 입력을 하면(Enter를 누르면) 입력한 것을 비워야 한다. 그런데 비우기 전에 value 값을 저장줘야 한다.
function handleToDoSubmit(event){
event.preventDefault();
const newTodo = toDoInput.value;
toDoInput.value="";
}
학습 날짜 : 23.08.11
To-Do-List를 화면에 추가해보자.
function paintToDo(newTodo){
}
function handleToDoSubmit(event){
event.preventDefault();
const newTodo = toDoInput.value;
toDoInput.value="";
paintToDo(newTodo);
}
toDoForm.addEventListener("submit", handleToDoSubmit);
toDo를 그리는 함수를 만들고, handleToDoSubmit 함수에서 호출하고 newTodo를 paintToDo 함수에 보낸다.(input에서 value를 얻어서 paintToDo 함수에 넘긴다.)
function paintToDo(newTodo){
const li = document.createElement("li");
const span = document.createElement("span");
li.appendChild(span);
span.innerText = newTodo;
toDoList.appendChild(li);
}
paintToDo 함수에서는 HTML ul태그 안에 li를 만들어 줄 것이다.
나중에 버튼을 넣을 것이기 때문에 li 안에 span을 이용해 newTodo를 넣어준다.
그 다음에 li를 toDoList에 추가해준다. toDoList.appendChild(li);
학습 날짜 : 23.08.11
To-Do-List에 toDo를 삭제하는 버튼을 만들어보자.
function paintToDo(newTodo){
const li = document.createElement("li");
const span = document.createElement("span");
span.innerText = newTodo;
const button = document.createElement("button");
button.innerText = "❌";
li.appendChild(span);
li.appendChild(button);
toDoList.appendChild(li);
}
사용자가 누르면 텍스트가 삭제되는 기능이 있다는 것을 인식시키기 위해 ❌ 버튼을 만들어주고, 버튼을 li에 넣어준다.
윈도우에서는 윈도우키
+
.
세개를 같이 눌러준다.
Mac에서는 control
cmd
space
세개를 같이 눌러준다.
버튼에 클릭 이벤트가 발생했을 때 삭제 기능을 담당하는 함수가 실행되도록 구현한다.
function deleteToDo(event){
const li = event.target.parentElement;
li.remove();
}
event.target.parentElement
학습 날짜 : 23.08.11
이번에는 실제로 toDo들을 저장해보자.
먼저 toDo들을 localStorage에 저장한다.
const toDos = [];
function saveToDos(){
localStorage.setItem("todos", toDos)
}
function handleToDoSubmit(event){
event.preventDefault();
const newTodo = toDoInput.value;
toDoInput.value="";
toDos.push(newTodo);
paintToDo(newTodo);
saveToDos();
}
toDos.push(newTodo);
localStorage.setItem("todos", JSON.stringify(toDos))
학습 날짜 : 23.08.12
toDos가 localStorage에는 저장되어 있지만 아직 화면에는 나타나진 않는다. 이번에는 화면에 나타내보자.
localStorage에는 String 타입만 저장할 수 있기 때문에 JSON.stringify로 배열처럼 생긴 String을 저장한다.
localStorage.setItem("todos", JSON.stringify(toDos))
그리고 다시 JSON.parse를 이용해 String 타입을 object로 바꿔준다.
JSON.parse(localStorage.getItem("todos"))
parsedToDos가 배열이라서 forEach를 이용할 수 있다.
function sayHello(item){
console.log("this is the turn of ", item);
}
//Arrow function
(item) => console.log("this is the turn of ", item)
위의 두 코드는 같은 코드이다.
학습 날짜 : 23.08.12
이제 parsedToDos 배열에 있는 item들을 화면에 그려보자.
전에 todos를 화면에 그리는 paintToDo 함수를 만들어뒀기 때문에 우리는 forEach 함수에 paintToDo만 넣어주면 쉽게 구현할 수 있다.
const TODOS_KEY = "todos";
const toDos = [];
function saveToDos(){
localStorage.setItem(TODOS_KEY, JSON.stringify(toDos));
}
function paintToDo(newTodo){
const li = document.createElement("li");
const span = document.createElement("span");
span.innerText = newTodo;
const button = document.createElement("button");
button.innerText = "❌";
button.addEventListener("click", deleteToDo);
li.appendChild(span);
li.appendChild(button);
toDoList.appendChild(li);
}
const savedToDos = localStorage.getItem(TODOS_KEY);
if(savedToDos !== null){
const parsedToDos = JSON.parse(savedToDos);
parsedToDos.forEach(paintToDo);
}
하지만, application이 시작될 때마다 toDos 배열은 항상 비어있기 때문에
const toDos = [];
newToDo를 작성하고 submit를 할 때마다 localStorage에 새로운 것만 저장된다.(기존에 저장되어 있던 list는 없어짐)
function handleToDoSubmit(event){
event.preventDefault();
const newTodo = toDoInput.value;
toDoInput.value="";
toDos.push(newTodo);
paintToDo(newTodo);
saveToDos();
}
newTodo만 toDos 배열(빈 배열)에 push하게 된다.
toDos.push(newTodo);
그리고 그 toDo를 저장할 때 새로운 toDo들만 포함된 배열을 저장하고 있다.
function saveToDos(){
localStorage.setItem(TODOS_KEY, JSON.stringify(toDos));
}
이전 것과 새로운 것을 모두 유지하고 저장해야 한다.
그러기 위해서는 application이 시작될 때 toDos 배열을 빈 값으로 시작하는 것이 아니라,
기존 const로 선언했던 것을 let으로 수정해 업데이트가 가능하도록 만들고
let toDos = [];
localStorage에 toDo가 있으면 toDos에 parsedToDos를 넣어서 전에 있던 toDo를 복원하면 된다. toDos = parsedToDos;
let toDos = [];
if(savedToDos !== null){
const parsedToDos = JSON.parse(savedToDos);
toDos = parsedToDos;
parsedToDos.forEach(paintToDo);
}
학습 날짜 : 23.08.13
toDoList에 삭제하는 버튼을 누르면 화면에서는 사라지지만 localStorage에는 그대로 남아있는 문제가 있다. 이번에는 그걸 해결해보자.
자바스크립트와 HTML 입장에서는 어떤 HTML의 요소를 지워야 하는지 알고 있지만, 어떤 toDo를 localStorage에서 지워야 하는지는 모른다.
어떤 item을 지워야 하는지 알아야 한다.
이번 강의에서는 toDo들에게 랜덤한 id를 설정해주어 각 li를 구별할 수 있도록 할 것이다.
Date.now()
를 이용해 id 값을 설정해준다.
Date.now()
는 밀리초를 주는 함수인데, 랜덤처럼 보인다. 이 함수를 사용해 랜덤 숫자를 받아서 id 값을 설정해주는 것이다.
object를 localStorage에 저장하도록 수정한다.
toDos.push(newTodo);
매번 사용자가 적은 text를 push하고 있다.
text 대신 object를 push할 수 있도록 수정한다.
const newTodoObj = {
text:newTodo,
id:Date.now(),
};
toDos.push(newTodoObj);
paintToDo 함수도 object인 newTodoObj를 받아 사용하도록 수정
paintToDo(newTodo);
→ paintToDo(newTodoObj);
newTodoObj는 text와 id를 가지고 있다. 텍스트를 출력할 때는 newTodo의 text 값을 가져와야 한다.
span.innerText = newTodo;
→ span.innerText = newTodo.text;
newTodoObj가 가지고 있는 id로 각 li item을 구별할 수 있다. li에 id 값을 설정해준다.
const li = document.createElement("li");
li.id = newTodo.id;
학습 날짜 : 23.08.13
array에서 요소를 삭제하는 방법을 알아보자.
parsedToDos.forEach(paintToDo);
array에서 뭔가를 삭제할 때 실제로 array에서 지우는 것이 아니다.
실제로 일어나는 일은 지우고 싶은 item을 빼고 새로운 array를 만드는 것이다.(item을 지우는 것이 아니라 제외한다고 생각하면 된다.)
arr.filter(callback(element, index, array), thisArg)
const arr = [1234, 5454, 223, 122, 45, 7655, 353];
function filterFunction(array){ return array <= 1000 };
arr.filter(filterFunction);
결과 : [223, 122, 45, 353]
학습 날짜 : 23.08.13
삭제 버튼을 누른 li의 id를 받고, 이 id를 제외하고 새로운 array를 만든다. 그리고 toDos array를 업데이트 한다.
toDos = toDos.filter(toDo => toDo.id !== li.id);
function deleteToDo(event){
const li = event.target.parentElement;
toDos = toDos.filter(toDo => toDo.id !== li.id);
li.remove();
}
이때, li.id의 타입은 String이고 toDo.id는 number 타입이어서 정상적으로 작동하지 않는다.
parseInt()를 사용해 String 타입을 number 타입으로 수정해준다.
toDos = toDos.filter(toDo => toDo.id !== parseInt(li.id));
그리고 삭제를 하고 나서 saveToDos 함수를 실행해주어야 한다.
(삭제한 것을 저장하기 위해)
function deleteToDo(event){
const li = event.target.parentElement;
li.remove();
toDos = toDos.filter(toDo => toDo.id !== parseInt(li.id));
saveToDos();
}