본문 바로가기
IT/JavaScript

JavaScript(2) ToDoList 만들기

by Sungjun_ 2020. 2. 12.

오늘은 자바스크립트로 ToDoList를 만들겠습니다.

 

먼저 toDo.html을 만들어 아래와 같이 작성해줍니다.

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="stylesheet" href="style.css">
</head>
<body>
    <h2>ToDoList</h2>
    <form class="js-form">
        <p><input type="text"></p>
    </form>
    <ul class="js-List">

    </ul>
    <script src="toDoList.js"></script>
</body>
</html>
/* css 파일 */
body{
    background-color: #1abc9c;
}

h2{
    margin-top: 100px;
    margin-left: 700px;
    
}

form{
    margin-top: 30px;
    margin-left: 700px;
}

form input[type=text]{
   font-size: 30px;
}

ul{ 
    margin-left: 700px;
    list-style-type: none;
}
li{
    font-weight: bold;
    font-size: 30px;
}

 

form 태그를 이용해 엔터를 누를 때 마다 input 박스에서 작성한, 할 일이 ul 안에 리스트로 생성되게 만들 것입니다.

toDo.html

 

 

이어서 toDoList.js 파일을 만들어줍니다.

그리고 앞에서 했던 시계 만들기와 마찬가지로 local Storage에 저장하겠습니다.

 

const toDoForm = document.querySelector(".js-form"),
    toDoInput = toDoForm.querySelector("input"),
    toDoList = document.querySelector(".js-List");

const TODOS_LS = "toDos"

function loadList(){
    const loadToDos = localStorage.getItem(TODOS_LS);
    toDoForm.addEventListener("submit",handleSubmit);
}


function show(){
    loadList();
}
show();

 

toDoForm, toDoInput, toDoList는 각각 toDo.html에 있는 form, input, ul을 가지고 온 것이고

TODOS_LS는 local Storage에 key 값으로 저장될 이름입니다.

 

함수 show는 최종적으로 toDoList를 화면에 출력해주는 함수입니다.

 

함수 loadList는  local Storage에 저장돼있는 toDoList를 가지고 오는 함수입니다.

그리고 toDoForm.addEventListener("submit",handleSubmit) 이 라인은

input 박스에 할 일을 적고 엔터를 치면 submit 이벤트가 발생하는데 submit 이벤트를 다루기 위한 핸들러를

추가한것입니다.

 

const toDoForm = document.querySelector(".js-form"),
    toDoInput = toDoForm.querySelector("input"),
    toDoList = document.querySelector(".js-List");

const TODOS_LS = "toDos"

function saveToDos(text){
    localStorage.setItem(TODOS_LS,text);
}

function showToDos(text){
    const li = document.createElement("li");
    const delBtn = document.createElement("button");
    li.innerText = text;
    delBtn.innerText = "X";
    li.appendChild(delBtn);
    toDoList.appendChild(li);
    saveToDos(text);
}

function handleSubmit(){
    const currentValue = toDoInput.value;
    showToDos(currentValue);
    
}

function loadList(){
    const loadToDos = localStorage.getItem(TODOS_LS);
    toDoForm.addEventListener("submit",handleSubmit);
    if(loadToDos !== null){
        showToDos(loadToDos);
    }
}

function show(){
    loadList();
}
show();

함수 loadList에 if 문을 추가해 값이 null이 아닐때만 showToDos()함수를 실행하게 바꿔줍시다.

 

함수 handleSubmit은 submit 이벤트를 다루기 위한 곳으로 currentValue에 input 박스에서 작성한 할 일을 넣어줍니다.

그리고 그 값을 showToDos 함수로 보내줍니다.

 

함수 showToDos는 ul 안에 li 태그로 할 일을 출력해주고, li 태그 안에 할 일을 삭제할 버튼을 넣어주어 출력해주는 부분입니다.

 

먼저 li 태그와 삭제 버튼을 만들어줍니다.

그리고 li.innerText로 li안에 handleSubmit에 보내준 값을 넣어줍니다. 

delBtn.innerText은 버튼안에 X라는 글자를 넣어 버튼이 X로 보이게 만들어준 것입니다.

li.appendChild는 li 태그 안에 삭제 버튼을 넣어준 것이고,

toDoList.appendChild는 ul 태그 안에 li태그를 넣어준 것입니다.

 

마지막으로 함수 saveToDos는 input 박스에서 작성한 할 일을 local에 저장시켜줍니다.

 

이제 작동을 하는지 살펴봅시다.

 

박스에 PHP를 치고 엔터를 누르면 PHP가 박스 아래쪽에 보이는 것을 확인 할 수 있고

 

local에도 저장된 것을 알 수 있습니다.

 

하지만 문제가 있습니다.

박스에 다른 할 일을 입력하면 PHP가 삭제되고 입력한 값으로 대체 될 것입니다.

 

 

화면도 JavaScript로 바뀌었을 뿐만 아니라, local도 PHP가 삭제되고 JavaScript로 바뀌었습니다.

 

이것을 해결하기 위해 배열과 객체를 사용하겠습니다.

 

let toDos = [];

function saveToDos(){
    localStorage.setItem(TODOS_LS,toDos);
}

function showToDos(text){
    const li = document.createElement("li");
    const delBtn = document.createElement("button");
    li.innerText = text;
    delBtn.innerText = "X";
    li.id = toDos.length + 1;
    li.appendChild(delBtn);
    toDoList.appendChild(li);
    toDoInput.value="";
    const toDoObj = {
        text: text,
        id: toDos.length + 1
    };
    toDos.push(toDoObj);
    saveToDos();
}

 

let toDos = []; 이렇게 하여 할 일을 넣어줄 빈 배열을 만들어줍니다.

 

그리고 함수 showToDos를 위와 같이 수정해줍니다.

li.id는 리스트가 입력 될 때마다 li 태그의 id에 숫자를 넣어줄 것입니다.

toDoObj를 만들고 text는 할 일이고, id는 할 일의 번호입니다.

id에 +1을 해준 이유는 1을 더해주지 않으면 0부터 시작하기 때문입니다.

toDoObj에 할 일이 저장될 때마다 그 값을 toDos.push로 toDos 배열에 넣어줍니다.

 

saveToDos(text)를 saveToDos()로 바꿔주고

함수 saveToDos에서 setItem 부분을 저렇게 바꿔줍니다.

 

이제 확인해봅시다.

 

입력했을 때 이렇게 객체로 저장되어있는 것을 확인 할 수 있습니다.

 

이 문제는 JSON을 이용해서 해결 할 수 있습니다.

아래와 같이 바꿔줍시다.

 

function saveToDos(){
    localStorage.setItem(TODOS_LS,JSON.stringify(toDos));
}



function loadList(){
    const loadToDos = localStorage.getItem(TODOS_LS);
    toDoForm.addEventListener("submit",handleSubmit);
    if(loadToDos !== null){
        const parseToDo = JSON.parse(loadToDos);
        parseToDo.forEach(function(toDo){
            showToDos(toDo.text);
        })
    }
}

함수 saveToDos와 loadList를 각각 저렇게 바꿔줍시다.

JSON.stringify는 객체를 문자열로 바꾸어 주는 것입니다.

 

함수 loadList를 보시면 forEach와 JSON.parse를 사용했는데

JSON.parse는 문자열로 저장돼있는 것을 다시 객체로 바꾸어 id와 text 중에서 text만 가지고오게 만들어주는 것입니다.

forEach는 배열에 있는 요소 하나하나를 실행해주는 것이라고 생각하시면 됩니다.

예를 들어 현재 local에 [(text : PHP, id : 1), (text : JAS, id : 2] 이렇게 들어 있다고 하면

저것을 각각 가지고 와서 PHP를 출력하고 JAS를 출력하게 해주는 것입니다.

 

이제 확인을 해보면

 

제대로 저장 및 출력 되는 것을 확인 할 수 있습니다.

 

이제 삭제 기능을 만들겠습니다.

 

function handleDelete(){
    const li = event.target.parentNode;
    toDoList.removeChild(li);
    const deleteToDos = toDos.filter(function(toDo){
        return toDo.id !== li.id;
    });
    toDos = deleteToDos;
    saveToDos();
}

function saveToDos(){
    localStorage.setItem(TODOS_LS,JSON.stringify(toDos));
}

function showToDos(text){
    const li = document.createElement("li");
    const delBtn = document.createElement("button");
    li.innerText = text;
    delBtn.innerText = "X";
    li.id = toDos.length + 1;
    delBtn.addEventListener("click",handleDelete);
    li.appendChild(delBtn);
    toDoList.appendChild(li);
    toDoInput.value="";
    const toDoObj = {
        text: text,
        id: toDos.length + 1
    };
    toDos.push(toDoObj);
    saveToDos();
}

먼저 showToDos함수 안에 delBtn.addEventListener("click",handleDelete) 이것을 추가해 버튼을 클릭할 때 마다 삭제가 되게 만들어줍니다.

그리고 handleDelete 함수를 위와 같이 작성해 줍니다.

const li는 이벤트가 발생하는 삭제 버튼의 부모 노드가 li이기 때문에 저렇게 작성해줍니다.

그리고 클릭했을 때 ul 안에 있는 li를 삭제해줍니다.

 

여기까지 작성을 하고 보면

 

1,2를 입력하고 2를 삭제 했을때 출력 상으로는 2가 사라졌지만, local에는 아직 2가 남아있는 것을 확인 할 수 있습니다.

 

const deleteToDos = toDos.filter(function(toDo){

        return toDo.id !== li.id;

});

 

filter 함수와 관련하여 아래 링크를 참고해주시기 바랍니다.

https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Array/filter

 

Array.prototype.filter()

filter() 메서드는 주어진 함수의 테스트를 통과하는 모든 요소를 모아 새로운 배열로 반환합니다.

developer.mozilla.org

 

toDos = deleteToDos;    

saveToDos();

 

toDos 배열을 deleteToDos로 바꿔주고 다시 local에 저장해줍니다.

 

이제 제대로 작동하는지 확인해봅시다.

 

PHP, JAS를 입력하고 삭제 버튼을 눌렀는데 아직 local에 값이 존재합니다.

 

function handleDelete(event){
    const li = event.target.parentNode;
    toDoList.removeChild(li);
    const deleteToDos = toDos.filter(function(toDo){
        console.log(toDo.id, li.id)
        return toDo.id !== li.id;
    });
    toDos = deleteToDos;
    saveToDos();
}

함수 안에 console.log(toDo.idli.id) 이 부분을 추가하고

오른쪽 창을 콘솔 창으로 바꾸어 주고 삭제 버튼을 눌러봅시다.

toDo.id는 숫자인데 li.id는 문자열로 출력 되는 것을 알 수 있습니다.

다음과 같이 바꿔줍시다.

 

function handleDelete(event){
    const li = event.target.parentNode;
    toDoList.removeChild(li);
    const deleteToDos = toDos.filter(function(toDo){
        return toDo.id !== parseInt(li.id);
    });
    toDos = deleteToDos;
    saveToDos();
}

li.id를 parseInt를 사용하여 숫자로 바꿔주었습니다.

 

다시 확인해봅시다.

 

 

PHP를 삭제 했을 때 로컬에서도 삭제되는 것을 볼 수 있습니다.

 

 

이것으로 마치겠습니다.

 

 

#참고 : https://academy.nomadcoders.co/courses/enrolled/435558

 

바닐라 JS로 크롬 앱 만들기

크롬 앱 클론코딩하며, JS 이론 배우기

[초급] HTML, CSS, JS

academy.nomadcoders.co

 

'IT > JavaScript' 카테고리의 다른 글

JavaScript(1) 시계 만들기  (1) 2020.02.03

댓글