TodoList 만들기 5

Yu Sang Min·2023년 11월 28일
1

JavaScript

목록 보기
24/25

filter()

  • 배열에서 지우고 싶은 아이템을 제외한다.
  • 그러나!!! 이전 배열은 여전히 남겨놓는다.
  • 때문에 지우고 싶은 아이템을 제외하고 새 배열을 만든다.

  • 위 콘솔을 보면 sexyFilter 함수는 반드시 true를 리턴한다.
  • 숫자 1부터 5까지 배열에 넣어주고 filter 함수에 인자로sexyFilter 함수를 넣어주면?
  • 1~5까지 숫자가 들어있는 배열이 반환된다.
  • 그러나 sexyFilter가 false를 리턴하게 수정한뒤 동일하게 filter 함수에 sexyFilter를 인자로 넣어주면?
  • 빈 배열이 반환된다.
  • filter 함수는 true를 반환하면 그 아이템을 새로운 배열에 넣고 false를 반환하면 새로운 배열에서 아이템을 제외한다.
  • 이는 forEach와 비슷하게 각 배열의 아이템 마다 함수를 실행하는 점에서 닮았다.

나는 이 부분에서 item을 매개변수로 받는데 그 item이 어떻게 배열의 요소로 자동으로 들어가게 되는지가 굉장히 이해가 어렵다.
=> JS가 array의 각 item을 sexyFunction의 첫번째 인자로 전달 해준다. 이건 정해져 있는 것이였다.

  • 일단 지금 sexyFilter 함수는 item이 3이면 false를 리턴한다.
  • 우리가 가진 배열에는 1~5까지의 숫자가 아이템으로 들어가있다.
  • filter 함수는 배열의 각각의 요소마다 sexyFilter 함수를 실행한다.
  • 3이 false이기 때문에 새로운 배열에 1,2,4,5를 담아 반환한다.

  • 다시 한번 보면 todos 변수에 배열을 할당하는데 이 배열의 아이템으로 객체가 들어가 있다.
  • 객체는 text라는 키와 문자열을 각각 가지고 있다.
  • sexyFilter 함수는 todo라는 매개변수를 받는다.
  • filter 함수를 사용할때 배열의 각 아이템을 인자로 전달한다.
  • sexyFilter 함수는 인자로 전달받은 객체의 text 키의 값이 문자열 lalal가 아니면 true를 반환한다.
  • todos배열의 메서드로 filter 함수의 인자로 sexyFilter 함수를 전달한다.
  • filter는 각 요소마다 함수를 실행하고 이때 객체의 text 키의 값이 lalal 이면 false를 반환하고 이 아이템을 제외한다.
  • 때문에 새로운 배열에는 text키의 값으로 hahahaha를 가진 객체가 배열에 담겨 반환된다.
function deleteToDo(e) {
    const li = e.target.parentElement;
    li.remove();
}
  • deleteToDo 함수는 HTML 요소중 X버튼을 누르면 호출된다.
  • filter를 이용해서 배열에 담긴 id값과 클릭했던 id값이 일치하면 false를 반환하게 하고 그 값을 제외한 새로운 배열이 반환되게 할것이다.
function deleteToDo(e) {
    const li = e.target.parentElement;
    li.remove();
    toDos = toDos.filter((toDo) => toDo.id !== li.id);
}
  • 화살표 함수를 이용 하여 코드를 간결하게 작성하였다.
  • return 하는 내용이 한줄이면 return과 중괄호도 생략이 가능.
  • toDos는 우리가 가지고 있는 배열이다.
  • 위 함수가 호출되면 toDos는 filter 함수에 의해 인자로 받은 배열의 아이템마다 화살표 이후의 로직을 실행한다.
  • toDo.id 가 li의 id와 동일하지 않으면 true를 반환하고, 동일하면 false를 반환한다.
  • 사용자가 X 버튼을 클릭하면 li.id로 클릭한 HTML 요소의 id값을 가져 올수 있었다.

위 코드의 결과:
콘솔에 toDos를 입력해 배열의 요소를 살펴보면 제대로 filter함수가 제대로 적용되지 않는다.

=> 브라우저 화면엔 a가 삭제되었지만 콘솔에 toDos를 참조하면 여전히 인덱스 0번에 객체로 a가 살아있다.

이는 파싱된 객체의 id값의 데이터 타입이 문자열이기 때문이다.

function deleteToDo(e) {
    const li = e.target.parentElement;
    li.remove();
    console.log(typeof li.id);
    toDos = toDos.filter((toDo) => toDo.id !== li.id);
}
  • 이를 console.log()에 typeof를 넣어 살펴보면?
    콘솔:

=> 콘솔에 string이라고 찍히는 모습

때문에 데이터 타입을 숫자로 변경해주어야 한다.

function deleteToDo(e) {
    const li = e.target.parentElement;
    li.remove();
    toDos = toDos.filter((toDo) => toDo.id !== parseInt(li.id));
}
  • parseInt를 이용하여 숫자타입으로 변환했다.
  • 이제 로컬스토리지에 fliter 함수가 반환한 새로운 배열을 저장한다.
function deleteToDo(e) {
    const li = e.target.parentElement;
    li.remove();
    toDos = toDos.filter((toDo) => toDo.id !== parseInt(li.id));
    saveTodos();
}
  • saveTodos 함수는 localStorage.setItem을 이용하여 toDos 배열을 저장한다.
  • JSON.stringify(toDos); 문자열로 변환하여 저장한다.
  • 자세한 코드는 아래 최종 JS파일 코드를 참고

결과:

새로운 배열을 로컬스토리지에 업데이트하는데 성공!

이로써 길고긴 todolist를 만드는데 성공하였다 물론 클론 코딩이지만!

지금까지 작성된 코드

<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Momentum App</title>
    <link rel="stylesheet" href="CSS/style.css">
</head>
<body>
    <form id="login-form" class="hidden">
        <input 
            required
            maxlength="10" 
            type="text" 
            placeholder="What is your name?" />
        <input type="submit" value="Log In" />
    </form>
    <h2 id="clock">00:00</h2>
    <h1 id="greeting" class="hidden"></h1>
    <form id="todo-form">
        <input type="text" placeholder="Write a To Do and Press Enter" required/>
    </form>
    <ul id="todo-list"></ul>
    <div id="quotes">
        <span></span><br/>
        <span></span>
    </div>
    <script src="JS/greetings.js"></script>
    <script src="JS/clock.js"></script>
    <script src="JS/Quotes.js"></script>
    <script src="JS/background.js"></script>
    <script src="JS/todo.js"></script>
</body>
</html>
JS

const toDoForm = document.querySelector("#todo-form");
const toDoList = document.querySelector("#todo-list");
const toDoFormInput = toDoForm.querySelector("input");

const TODOS_KEY = "todos";

let toDos = [];

function saveTodos () {
    localStorage.setItem(TODOS_KEY, JSON.stringify(toDos));
}

function deleteToDo(e) {
    const li = e.target.parentElement;
    li.remove();
    toDos = toDos.filter((toDo) => toDo.id !== parseInt(li.id));
    saveTodos()
}

function paintToDo (newToDo) {
    const li = document.createElement("li");
    li.id = newToDo.id;
    const span = document.createElement("span");
    span.innerText = newToDo.text;
    const button = document.createElement("button");
    button.innerText = "❌";
    button.addEventListener("click", deleteToDo);
    li.appendChild(span);
    li.appendChild(button);
    toDoList.appendChild(li);
}


function handleTodoSubmit (e) {
    e.preventDefault();
    const newToDo = toDoFormInput.value;
    toDoFormInput.value = "";
    const newToDoObj = {
        text: newToDo,
        id: Date.now(),
    }
    toDos.push(newToDoObj);
    paintToDo(newToDoObj);
    saveTodos();
}


toDoForm.addEventListener("submit", handleTodoSubmit);

const savedToDos = localStorage.getItem(TODOS_KEY);

if (savedToDos !== null) {
    const parseToDos = JSON.parse(savedToDos);
    toDos = parseToDos;
    parseToDos.forEach(paintToDo);
}
profile
프론트엔드 개발자 지망생

0개의 댓글