[JavaScript] ToDo리스트 만들기
in JavaScript on Study
1️⃣ 목표
- 이번에는 ToDo리스트기능을 구현해볼 예정입니다.
<form id="A17-todo">
<input type="text" placeholder="what to do" required />
</form>
<ol id="A17-todo-list"></ol>
html
의 기본 형태는 위와 같습니다.todo(할 것) 을 submit으로 받기 위해form
태그를 사용하여 입력을 받았습니다.- 입력받은 값은
ol(번호가 달린 리스트)
태그안에li(리스트) 형태로 순차적으로 추가됩니다. - 새로고침이후에도 정보가 유지되기 위해 LocalStorage를 임시로 이용할 계획입니다.
2️⃣ 새롭게 배운 주요기능들
(1) 배열 push()함수
새로고침 이후에도 Todo리스트가 유지되기 위해서는 LocalStorage를 이용해야 합니다. 즉, 이전에 배운localStorage.setItem()
이용하여 입력받은 값을 일리리 저장해주는 과정이 필요합니다.- 추가로
리스트 제거, 리스트 완료표시 기능도 넣어야 되기 때문에배열형태 로 저장해야합니다.
let toDos = [];
const toDoInput = document.querySelector("#A17-todo input");
function submitFunc(event)
event.preventDefault();
const newInput = toDoInput.value;
const newObj = {
text: newInput,
id: Date.now(),
is_done: false,
}
toDoInput.value = "";
toDos.push(newObj);
saveToDos();
paintToDo(newObj);
}
/* saveToDos() */
function saveToDos() {
localStorage.setItem(TODO_KEY, JSON.stringify(toDos));
}
- 위처럼 입력값에 대한 정보가 닯긴
배열(newObj) 을 local storage로 최종적으로 넘겨줄배열(toDos) 에.push()
메소드를 이용하여 추가해 줍니다. id
값은 현재시간을 (ms)단위로 변환한 값을 주는Date.now()
를 이용했습니다.saveToDos()
메소드에서는 최종적으로 local storage로 데이터를 넘겨주게 됩니다.
(2) JSON.stringify()
위에서 local storage로 데이터를 넘겨주기 위해 toDos배열을
JSON.stringify()
메소드로 포맷팅을 해준뒤 넘겨주었습니다.여기서
JSON
은 “키-값 쌍”으로 이루어진 데이터 오브젝트를 전달하기 위해 인간이 읽을 수 있는 텍스트를 사용하는 개방형 표준 포맷입니다. 자세한 설명은 아래의 사이트를 참고면 됩니다.
👉🏻 👉🏻 👉🏻 JSON - 위키백과 👉🏻 👉🏻 👉🏻 JSON개념 - 드림코딩 by 엘리포매팅을 해주지 않으면 다음과 같이
object 로 표시되어 어떤 값이 저장되어있는지 확인하기 힘듭니다. (정상적으로 작동하기는 하다)console.log() 출력값은 다음과 같습니다.
포매팅하지않은 toDos 콘솔출력
JSON.stringify()사용후 toDos 콘솔출력
- 위와 같이 알아볼 수 있는 값으로 성공적으로 표시 되었습니다.
(3) forEach()
const savedToDos = localStorage.getItem(TODO_KEY);
if (savedToDos !== null) {
const parsedToDos = JSON.parse(savedToDos);
toDos = parsedToDos;
parsedToDos.forEach(paintToDo);
}
- 새로고침했을때 마다 위의 로직이 실행되어 LocalStorage에서 데이터를 가져와서
파싱 해줍니다. JSON
에서parse()
는stringify()
와 반대로 JSON 문자열의 구문을 분석하고, 그 결과에서 JavaScript값이나 객체를 생성합니다.
savedToDos 콘솔출력
JSON.parse사용후 콘솔출력
parse
로 파싱이 완료된 parsedToDos는 배열형태입니다.forEach()
메소드를 이용하면 배열의 모든 요소를 인자로 받은 메소드를 호출해줍니다.- 노드를 메소드의 매개변수로 자동으로 넘겨줍니다.
(4) filter()
function deleteToDo(event) {
const target = event.target.parentElement;
target.remove();
toDos = toDos.filter((toDos) => toDos.id !== parseInt(target.id));
saveToDos();
}
- 삭제버튼을 누르는 이벤트를 하면
deleteToDo()
메소드를 호출합니다. event.target
는 버튼의 태그인<button>
을 가리키고event.target.parentElement
는 취소버튼의 부모노드인<li>
를 가르키게 됩니다. 즉,<li>
인event.target.parentElement
를 삭제해야 정확히 리스트를 한개 삭제할 수 있습니다.- 하지만 역시 LocalStorage에서의 데이터도 업데이트 시켜줘야 합니다.
filter()
메소드를 이용하면forEach()
메소드와 같이 배열의 모든 요소마다특정 메소드 를 호출하여줍니다. 만약특정 메소드 가 false(거짓)이 아닌 true(참)을 반환한 값들만을 모아둔 배열을 만들어 반환합니다.- 타겟노드는 바뀌지않고
반환값 으로만 변환된 배열을 얻을 수 있습니다. 그러므로toDos
변수로 다시 받아줍니다. filter()
메소드는 위와같이=>
기호를 이용하여 메소드 대신 간단한 boolean형 조건문으로 대체 가능합니다.
3️⃣ 취소선으로 체크기능 넣기
(1) css, html
- 취소선을 만들 수 있는 것은
html 과 css모두 기능이 있습니다.html 에서 태그를<s>
로 바꾸기- css에서
text-decoration
요소 이용하기
- 위의 방법중
html 를 수정해주는 코드는 자바스크립트에서 노드의 HTML요소를 수정하는 방법으로 바꿔줄 수 있습니다. 하지만 이런식으로태그 를 변경해주면 기존에 있던 이벤트함수이 원하는데로 작동하지 않는 현상이 발생했습니다. (어떻게든 이벤트함수가 동작하도록 만들 수 있지만 코드가 너무 복잡해짐) - 또한 인터넷상에서도
css에서 구현된 기능은 되도록이면 js대신 css를 이용 하는 것이 효율적이라고 말합니다.
/* style.css */
.A17-del {
text-decoration: line-through;
color: red;
}
/* todo.js */
function doneFunc(event) {
const tar = event.target.parentElement;
for (const i in toDos) {
if (toDos[i].id === parseInt(tar.id)) {
if (toDos[i].is_done === true) {
event.target.classList.remove("A17-del");
toDos[i].is_done = false;
} else {
event.target.classList.add("A17-del");
toDos[i].is_done = true;
}
}
}
saveToDos();
}
css
를 이용하면 위의코드만으로 간단하게 기능을 구현할 수 있습니다.
4️⃣ 최종 결과물
- todo(할 것)을
최대 40자 까지 작성하여 추가할 수 있습니다. - todo(할 것)를
클릭 하여 체크선을 그리거나 지워줄 수 있습니다. - X 버튼을 눌러서 특정 todo(할 것)을 지울 수 있습니다.