자바스크립트로 ToDo리스트같은 간단한 프로그램을 만들었을 때,
새로고침을 하면 목록들이 사라집니다.
목록을 저장하기 위해서는 'localstorage'를 사용합니다.
텍스트를 입력해 화면에 ToDoList를 출력해주면 그 리스트들을 먼저 localstorage에 저장하고,
새로고침했을 때, localstorage에서 불러와 화면에 출력을 해준다.
const toDos = [];
ToDoList를 출력한 텍스트들을 toDos라는 배열에 push 해줍니다.
const value = toDoInput.value // 화면에 출력할 todo 목록의 값들
toDos.push(value);
여기서 문제는 localstorage에는 배열을 저장하는 것이 불가능합니다.
오직 텍스트만 저장할 수 있어요.
이대로 localstorage에 저장하게 되면 배열 안에 있는 값들만이 문자열로 들어오게 됩니다.
이럴때 자바스크립트의 객체나 배열의 어떤 것이든 문자열로 바꿔주는 기능이 있습니다.
JSON.stringify()
이 JSON.stringify()를 사용한다면 객체나 배열 등 어떤 것이든 문자열로 만들어 줍니다.
localStorage.setItem("todos", JSON.stringify(toDos));
이러한 형태로 작성할 수 있는데,
이렇게만 한다면 "[\"a"\","b\",\"c\"]" 이러한 형태로 배열 그대로를 문자열로 변환을 하게 됩니다.
이것을 JSON.parse() 안에 넣어주면 온전히 살아있는 배열을 얻게 됩니다.
그러면 실제로 활용할 수 있는 배열을 localstorage에 저장이 되었으니 이것을 활용해서
출력만 해주면 됩니다.
const savedToDos = localStorage.getItem("todos");
const parsedToDos = JSON.parse(savedToDos);
parsedToDos.forEach((toDo) => {
const $li = document.createElement('li');
$li.append(toDo);
});
하지만 여기서도 문제 하나가 있습니다.
위에서 const toDos = []; 로 설정이 되어 있어서 새로고침을 하게 되면 기존에 있던 배열에 있는
값이 사라지고 새로 저장되는 값만 다시 빈 배열안에 저장이 됩니다.
때문에 const toDos = []; 이 부분을 let으로 바꿔준 뒤,
업데이트가 가능해지도록 해주고 localstorage에 값이 있다면 localstorage에 저장된 배열을
toDos에 다시 저장을 해줍니다.
let toDos = [];
.
.
.
const savedToDos = localStorage.getItem("todos");
if(savedToDos) {
const parsedToDos = JSON.parse(savedToDos);
toDos = parsedToDos;
parsedToDos.forEach((toDo) => {
const $li = document.createElement('li');
$li.append(toDo);
});
}
이렇게 해준다면 새로고침을 해도 localStorage에 저장된 배열을 toDo로 불러옵니다.
하지만 삭제한 리스트까지도 새로고침 후 반영하지는 않습니다.
화면에서 toDo 리스트 목록들을 삭제하더라도 localStorage에서까지 삭제가 되지는 않습니다.
localStorage에서 원하는 아이템을 삭제하기 위해서는 해당 아이템에 id가 필요합니다.
이때 자주 사용되는 것이
Date.now(); // 밀리초 (1000분의 1초)를 주는 함수
입니다.
toDos라는 배열에 input값을 저장하는 대신, id가 포함된 객체를 저장해 줍니다.
const newTodoObj = {
text: value,
id: Date.now(),
}
저장된 객체를 toDos에 푸쉬해준 뒤, text를 출력해 줍니다.
여기서 id는 각각의 item을 구별하기 위해 넣어준 겁니다.
toDo목록을 만들어주기 위해 li태그를 생성해줌과 동시에 id를 부여해 줍니다.
const $li = document.createElement('li');
$li.id = newToDo.id;
이제 내가 지우고 싶은 아이템을 지우기 위해 'filter'함수를 사용할 겁니다.
정확히는 특정한 아이템을 지우는 것이 아닌,
지우고 싶은 item을 빼고 새 배열을 반환해주는 역할을 해줍니다.
[1, 2, 3, 4].filter(() => {
});
위 함수에서 배열이 가지고 있는 1,2,3,4라는 숫자를 forEach 함수처럼 각각의 요소에 함수를 실행 시키는데 이때, 함수에서 true를 반환하는 요소만을 새로운 배열로 만들어 줍니다.
[1, 2, 3, 4].filter((item) => {
return item !== 3;
});
이렇게 해줬을 때 1~4까지의 배열중에서 3이 아닌 요소를 반환해 새로운 배열을 만들어 준 것입니다.
이것을 이용해서 내가 클릭한 아이디와 내가 삭제하고 싶은 아이디가 다른 것들을 새로 배열로 모아서 만들어주고 삭제하고 싶은 아이디를 가지고 있는 아이템은 삭제를 해줄 겁니다.
화면상에서 내가 지우고 싶은 아이템을 삭제하는 버튼을 클릭했을 때,
toDos = toDos.filter((toDo) => toDo.id !== li.id);
위 코드로 지워주는데 이때, toDo.id는 number타입이고, li.id는 string타입이기 때문에
제대로 지워지지 않습니다.
toDos = toDos.filter((toDo) => toDo.id !== parseInt(li.id));
그래서 parseInt를 사용해 줍니다.
마지막으로
localStorage.setItem("todos", JSON.stringify(toDos));
한번 더 불러와 줍니다.