- to-do List 추가, 삭제 기능
- to-do 가 만들어진 시간 기록
- 애니메이션 효과
- to-do List LocalStorage 저장
- 화면 출력시 정렬
to-do list
는 나갔다가 들어와도, 또는 새로고침을 해도 원래 내용이 그대로 유지되어야 하기 때문에, LocalStorage에 to-do list
를 통째로 저장해 내용이 유지되도록 만들어볼 계획이다.
뭔가 도전할 때 항상 생각나는 짤
- 데이터를 로컬에 저장한다.
- 데이터 저장, 삭제 등 javascript 로 조작하여 사용 가능하다.
- 유효기간이 없다.
- key value 한 쌍으로 저장된다.
저번 오랑우톡 개발할 때 쿠키를 써보았는데, 쿠키와 사용법이 비슷하면서도.. 좀 달라서 찾아보면서 써보았다.
// localStorage 객체 형태로 저장
const obj = {'keyValue':keyValue,'text':text, 'time':nowTime};
localStorage.setItem(text, JSON.stringify(obj));
// localStorage 객체 불러오기
const localObj = JSON.parse(localStorage.getItem(text));
// todo div 만들기
makeTodo(localObj);
// 스크롤 맨 아래로 고정
mainDiv.scrollTop = mainDiv.scrollHeight;
// input 값 초기화
inputValue.value = '';
먼저 obj
라는 이름의 객체 하나를 만든다. 이 객체 안에는 keyValue
, text
, time
이 세 개의 key와 value 값이 들어간다.
방금 저장한 로컬스토리지 객체를 text
값으로 불러와 Todo 를 만드는 함수인 makeTodo
에 인자로 보내 todo 한 블록을 만들게 한다.
❗ 이때 유의해야할 점은
value
로는 무조건string
밖에 저장이 안 되기 때문에object(객체) -> string(문자열)
으로 변환을 해주어야 한다.
const del = () => {
// todo 의 부모를 찾아서 todo 를 삭제
const div = event.target.parentNode
mainDiv.removeChild(event.target.parentNode);
// localStorage key 값에 해당하는 text에 접근
const key = div.childNodes[0].childNodes[0].innerHTML;
localStorage.removeItem(key);
}
del
함수 뒷 부분에 삭제할 값을 key(text 내용)
로 찾아 로컬스토리지에서 remove
해주는 코드를 추가해주었다. ❗ 로컬스토리지는 단순 저장밖에 되지 않는다. 즉, 순서는 상관 없이 저장된다.
실제로 리스트를 저장하고 개발자도구로 저장된 값을 확인해보면
1,2,3,4,5 순으로 저장했음에도 불구하고 순서가 뒤죽박죽인 것을 확인할 수 있다.
나는 추가한 순서대로 화면에 출력하고 싶기 때문에, 객체를 생성할 때 넣어준 keyValue
로 로컬스토리지의 객체들을 정렬시킨후, 화면에 출력해줄 것이다.
const list = () => {
// localStorage key 값으로 list 를 만드는 과정
for(let i=0; i<localStorage.length; i++) {
const localObj = JSON.parse(localStorage.getItem(localStorage.key(i)))
sortList.push(localObj);
}
// sortList 정렬 후 출력
for (let item=0; item<sortList.length; item++){
keyList.push(sortList[item].keyValue);
}
// 정렬
keyList.sort();
// 정렬된 key 로 맞는 value 찾고, 새로운 리스트
//sortedList 에 순서대로 저장.
for (let i=0; i<keyList.length; i++) {
for (let j=0; j<sortList.length; j++) {
if (sortList[j].keyValue === keyList[i]) {
sortedList.push(sortList[j]);
} else {
continue
}
}
}
// 중복제거
const norepeatList = Array.from(new Set(sortedList));
// 정렬된 리스트로 List 출력
for (let i=0; i<norepeatList.length; i++) {
makeTodo(norepeatList[i]);
}
}
위의 코드는 크게 세 단계로 구성되어있다.
LocalStorage 에서 keyValue
값을 for 문으로 하나씩 꺼내와 list
에 저장한다.
keyValue
가 저장된 list
를 sort
로 정렬해준 후 정렬된 list
를 for 문을 다시 돌려 keyValue 에 해당하는 객체를 찾아 다시 새로운 list
에 저장해준다.
❕ 여기까지 함으로써 정렬된 keyValue(1,2,3 ...)
의 순서대로 LocalStorage 객체들이 list
에 저장되었다.
정렬된 객체들이 저장된 list
를 for문으로 화면에 출력해준다.
위의 움짤을 보면 알 수 있듯이, 새로고침시에는 정렬이 잘 되지만 (원래는 순서가 전부 뒤바뀌어야한다.)
특정 to-do 를 삭제 후 새로운 to-do 를 생성하고 다시 새로고침 하면 순서가 뒤바뀐다. 이 부분에서 애를 정말 많이 먹어서 다양한 방법을 시도해보았다.
// 정렬
if (localStorage.length > 0){
keyValue = localStorage.length+1
let maxNum = 0;
// max 구할 수 없는 경우
if (keyList.length === 1) {
maxNum = keyList.length;
} else {
maxNum = (Math.max.apply(null, keyList))+1;
}
} else {
keyValue += 1
}
LocalStorage 에 아무값도 없을 경우에 keyValue
의 최대값을 찾아 새로 to-do 를 추가할시 keyValue 값을 최대값에서 1 더해준 값으로 저장하는 코드를 짰다. 생각해보니 keyValue
값을 maxNum
으로 지정을 안 해주어서 이 코드는 당연히 안 되는 것이였다 ^-^
// 정렬
if (localStorage.length > 0){
// max 구할 수 없는 경우
if (localStorage.length === 1) {
maxNum = sortedKey.length +1;
keyValue = maxNum;
} else {
maxNum = (Math.max.apply(null, sortedKey))+1;
keyValue = maxNum;
}
} else {
keyValue += 1
}
그래서 같은 방식으로 다시 짰다.
몇 시간을 잡고 해봐도 도저히 안 고쳐졌다...
며칠 뒤에 다시 보면 뭔가 생각이 나지 않을까 싶어 여기까지 해두었다가 오늘 오랜만에 다시 해보았는데, 문제를 찾아버렸다 !
문제는..
sortedKey
!
sortedKey
가 전역적으로 선언된 list
가 아닌, 화면에 출력하는 함수 내에서 선언된 list
여서 항상 빈 리스트로 나왔던 문제였다.
그래서 todo 를 만드는 함수에도 다시 sortedKey
를 만들어주었다.
const toDo = () => {
const normalList = [];
const sortedKey = [];
const nowTime = makeTime()
for(let i=0; i<localStorage.length; i++) {
const localObj = JSON.parse(localStorage.getItem(localStorage.key(i)))
normalList.push(localObj);
}
// sortList 정렬 후 출력
for (let item=0; item<normalList.length; item++){
sortedKey.push(normalList[item].keyValue);
}
// 정렬
sortedKey.sort();
// input 에 들어온 text 설정
let text = inputValue.value;
let maxNum = 0;
// 정렬
if (localStorage.length > 0){
// max 구할 수 없는 경우
if (localStorage.length === 1) {
maxNum = sortedKey.length +1;
keyValue = maxNum
} else {
maxNum = (Math.max.apply(null, sortedKey))+1;
keyValue = maxNum;
}
} else {
keyValue += 1
}
이렇게 맨 첫부분에 sorted list
를 다시 한 번 선언해주었다.
특정 상황에서 순서가 다시 뒤바뀌는 문제가 발생했다. 다행히 원인을 바로 알 수 있었다.
if (localStorage.length === 1) {
maxNum = sortedKey.length +1;
keyValue = maxNum
바로 이 부분이다. 남은 todo list
길이가 1
일시 새로 to-do 를 추가하면 무조건 maxNum
이 2가 되어버려 순서가 뒤바뀌었다.
if (localStorage.length === 1) {
maxNum = sortedKey[0] + 1;
keyValue = maxNum
길이가 1이라는 것은 어차피 list
에 요소가 하나라는 뜻이므로, index 0
을 찾아 이 요소의 keyValue
보다 하나 더 큰 값으로 새롭게 생길 to-do 의 keyValue
값을 지정해주었다.
새로고침 & 중간에 요소 삭제 및 추가를 해도 순서대로 정렬 된다.
TODO LIST
를 만들면서 기본기를 다진 것 같아 기분이 아주 좋다. Bug
를 해결해서 뿌듯했다. JS
에 자신감도 붙고, 더 많이 알게된 것 같아 행복했다. 역시 JS 는 최고다 ! : )