• 카테고리

    질문 & 답변
  • 세부 분야

    프로그래밍 언어

  • 해결 여부

    해결됨

아 네~다시 질문드립니다.

23.10.10 15:00 작성 23.10.10 15:00 수정 조회수 125

0

아 네네...그렇제 않아도 제가 안눌렀는데 해결로 되어 있어써.ㅡㅡ

파일은 첨부가 안되는 거 같아서 깃허브에 올려서 링크를 연결해두었습니다.

강사님 수업을 듣고 나름대로 조금 수정을 해봤습니다. 우선 삭제버튼을 아이콘폰트로 바꾸고 전체 개수와 전체 삭제등을 추가했구요,

근데, 문제가 발생한것이 처음엔 목록을 몇개 만들어보고 삭제버튼을 클릭해보면 화면로 로컬스토리지가 잘 삭제가 돌일하게 잘 되었구요, 그런 다음 새로고침을 눌러도 변함없는 확인하기 위해 새로고침을 누르고 다시 아무거거 한개 삭제버튼을 한번 더 눌러보면 화면에서는 누른것만 지워졌는데, 로컬스토리지에서는 어떤 항목의 삭제버튼을 눌어도 무조건다 지워진 빈 배열이 되어서요....

 

 

https://github.com/web1004/ask

 

 

답변 1

답변을 작성해보세요.

0

우선, init() 함수에서 만약 로컬스토리지에 저장된 todos가 있다면 그것을 파싱 해오는데, 그것을 페이지 내에서 조작하기 위해서 사용하는 글로벌 변수 todos에 넣는 과정이 없습니다. 그렇기 때문에 로컬스토리지에는 있고, 글로벌 변수에는 없어서, 마치 제대로 저장되고 복원 되는 것처럼 보이지만, 조작하면 (조작하는 대상은 글로벌 변수 todos 이므로) 문제가 생기게 됩니다.

 

// 페이지 내에서 조작하는 todos는 글로벌 변수인 todos 입니다.
let todos = [];

const init = () => {
  // 이 친구는 어디로?
  const userTodos = JSON.parse(localStorage.getItem('todos'));

  if (userTodos) {
    userTodos.forEach((todo) => {
      addItem(todo);
    });

    // 아래 부분을 추가해 주어야 합니다.
    todos = userTodos;
  }
};

 

또한 init() 함수에서 로컬스토리지에 저장된 항목이 있음에도 불구하고 todoCount.textContent를 0으로 초기화 하고 있습니다. 추측컨데, 이 기능이 올바르게 작동하려면 0으로 초기화 하는 것이 아니라, 저장된 개수를 세서 넣어줘야 할 것으로 보입니다.

 

const init = () => {
  const userTodos = JSON.parse(localStorage.getItem('todos'));

  if (userTodos) {
    userTodos.forEach((todo) => {
      addItem(todo);
    });

    todos = userTodos;

    // 다음과 같이 수정되어야 합니다.
    updateTodoCount();
  }
};

 

추가로, 더 정확히는, 이 기능은 저장된 배열이 있던 없던 저장된 항목의 개수를 세어 표기하는 기능으로 보이기 때문에, 다음과 같이 if문 밖에 작성되어야 할 것 같습니다. 그래야 저장된 항목이 없어도 0 task 라고 표기됩니다.

 

const init = () => {
  const userTodos = JSON.parse(localStorage.getItem('todos'));

  if (userTodos) {
    userTodos.forEach((todo) => {
      addItem(todo);
    });

    todos = userTodos;
  }

  updateTodoCount();
};

 

세 번째로, 전체 삭제 함수에서 임의로 테스크 개수를 0이라고 덮어씌울 필요없이, 이미 글로벌 변수 todos의 모든 내용을 지웠기 때문에 그냥 개수를 세는 함수를 호출하시면 됩니다.

 

clearAll.addEventListener('click', () => {
  ul.innerHTML = '';
  todos = [];
  localStorage.removeItem('todos');
  updateTodoCount();
});

 

네 번째로, 이미 이벤트 핸들러에서 input.value !== ''임을 체크하고 공백이 아닌 것들만 addItem() 함수를 실행하고 있기 때문에, 중복으로 검증하실 필요는 없습니다. 따라서 if문을 핸들러 안에 두신다면 다음과 같이 수정하셔도 됩니다.

 

const addItem = (todo) => {
  const li = document.createElement('li');
  const span = document.createElement('span');
  const icon = document.createElement('i');
d
  icon.classList.add('fa-solid', 'fa-trash-can');
  span.innerText = todo.text;
  icon.addEventListener('click', delItem);

  ul.appendChild(li);
  li.appendChild(span);
  li.appendChild(icon);
  li.id = todo.id;

  updateTodoCount();
};

 

수정된 전체 코드

const form = document.querySelector('form');
const input = document.querySelector('input');
const ul = document.querySelector('ul');
const todoCount = document.querySelector('.todo-count');
const clearAll = document.querySelector('.clear-all');

let todos = [];

const save = () => {
  localStorage.setItem('todos', JSON.stringify(todos));
};

const updateTodoCount = () => {
  todoCount.textContent = todos.length;
};

const clearItems = () => {
  ul.innerHTML = '';
  todos = [];
  localStorage.removeItem('todos');
  updateTodoCount();
};

const delItem = (event) => {
  const target = event.target.parentElement;

  todos = todos.filter((todo) => todo.id !== parseInt(target.id));

  save();
  target.remove();
  updateTodoCount();
};

const addItem = (todo) => {
  const li = document.createElement('li');
  const span = document.createElement('span');
  const icon = document.createElement('i');

  icon.classList.add('fa-solid', 'fa-trash-can');
  span.innerText = todo.text;
  icon.addEventListener('click', delItem);

  ul.appendChild(li);
  li.appendChild(span);
  li.appendChild(icon);
  li.id = todo.id;

  updateTodoCount();
};

const handler = (event) => {
  event.preventDefault();

  const todo = {
    id: Date.now(),
    text: input.value,
  };

  if (input.value !== '') {
    todos.push(todo);
    addItem(todo);
    save();
    input.value = '';
  }
};

const init = () => {
  const userTodos = JSON.parse(localStorage.getItem('todos'));

  if (userTodos) {
    userTodos.forEach((todo) => addItem(todo));
    todos = userTodos;
  }

  updateTodoCount();
};

init();
form.addEventListener('submit', handler);
clearAll.addEventListener('click', clearItems);
gangsugi님의 프로필

gangsugi

질문자

2023.10.11

아...너무나 자세한 설명 정말 감사드립니다.

내가 무엇이 틀렸는지 정확하게 알게 되네요....다시 한번 감사드립니다....

더 공부를 해야겠네요..ㅋㅋㅋ