동백 // 노마드 코더 바닐라JS: TO DO LIST

2021. 11. 9. 15:04FrontEnd

반응형

출처 : https://nomadcoders.co/

 

Setup

 

핵심 : To do list를 위해 기본 환경을 세팅한다.

 

0. todo.js를 만들어주고, html에 import해준다.

 

1. 사용자가 todo를 입력하는 것을 입력받을 form이 필요하다.

    <form id="todo-form">
        <input type="text" placeholder="write a To Do and press Enter" required/> 
    </form>

<!-- required는 필수로 사용자가 입력해야 함을 의미한다. -->

 

 

2. todo-list라는 id를 가진 ul을 만들어준다.

    <ul id="todo-list">
        <li></li>
    </ul>

<!-- JS에서 li를 채울것이기에 지금은 비워놓도록 하자 -->

 

 

3. form과 ul을 HTML에서 JS로 가져온다.

const toDoForm = document.getElementById("todo-form");
const toDoList = document.getElementById("todo-list");

 

4. greeting의 form에서 했던 것을 똑같이 반복해줌 (submit시 브라우저의 기본 동작인 새로고침이 되는 issue)

function handleToDoSubmit(event) {
    // submit시 브라우저의 기본 동작인 새로고침 되는 것을 막아줌.
    event.preventDefault();
}

toDoForm.addEventListener("submit", handleToDoSubmit);

 

5. HTML form에서 입력받은 input의 value를 js로 가져온다.

// 위에서 미리 todo-form을 찾아놨기에 toDoForm을 통한 element 연결 가능
const toDoinput = toDoForm.querySelector("input");

 

6. 입력 후 Enter를 누를 때 마다 입력한 것을 비우고 싶을 때, 즉 Enter를 누르면 모든 입력값이 사라짐

Tip // toDoInput의 value에 빈 값("")를 넣어주면 됌.

 

function handleToDoSubmit(event) {
    // submit시 브라우저의 기본 동작인 새로고침 되는 것을 막아줌.
    event.preventDefault();
    // input value를 비우기 전에 그 값을 다른 변수에 저장해줌.
    const newTodo = toDoinput.value;
    toDoinput.value = "";
}

 

 


 

 

Adding toDos

 

핵심 : To do list에 toDo를 추가한다.

 

1. toDo를 그리는 function을 만든다.

// submit된 newTodo를 매개변수로 받음
function paintToDo(newTodo) {
 

}

 

2. HTML todo-list에 JS에서 li를 추가해주고, li 내부에다 span을 만들어준다.

tip // span은 div와 다르게 줄바꿈이 되지않는다.

// submit된 newTodo를 매개변수로 받음
function paintToDo(newTodo) {
    // HTML에 li라는 element를 만들어줌
    const li = document.createElement("li")
    // HTML에 span이라는 element를 만들어줌
    const span = document.createElement("span");
    // span을 li의 자식 element로 추가함. = li 내부에 span을 추가해줌
    li.appendChild(span);
    // span에 newTodo(입력받은 toDo)를 입력해줌.
    span.innerText= newTodo;

}

 

3. 새로운 li를 html의 list(toDoList)에 추가해줌.

tip // HTML과 연결을 해야 화면에 출력이 됨.

// submit된 newTodo를 매개변수로 받음
function paintToDo(newTodo) {
    // HTML에 li라는 element를 만들어줌
    const li = document.createElement("li")
    // HTML에 span이라는 element를 만들어줌
    const span = document.createElement("span");
    // span을 li의 자식 element로 추가함. = li 내부에 span을 추가해줌
    li.appendChild(span);
    // span에 newTodo(입력받은 toDo)를 입력해줌.
    span.innerText= newTodo;
    // HTML의 toDo-list에 li(내부에 span이 있는)를 자식 element로 추가해줌.
    toDoList.appendChild(li);
}

HTML 내부에서도 li와 span이 생성됨.

 

 

 

 


 

 

Deleting toDos

 

핵심 : todo가 새로고침하면 사라지는 문제와 삭제하지 못하는 문제를 해결한다. 

 

 

1. toDo를 삭제하는 button을 JS에서 추가하고, li 내부에다 button을 만들어준다.

tip // append는 항상 마지막에 위치해야 함.

// submit된 newTodo를 매개변수로 받음
function paintToDo(newTodo) {
    // HTML에 li라는 element를 만들어줌
    const li = document.createElement("li");
    
    // HTML에 span이라는 element를 만들어줌
    const span = document.createElement("span");
    // span에 newTodo(입력받은 toDo)를 입력해줌.
    span.innerText= newTodo;
    
    // HTML에 button이라는 element를 만들어줌
    const button = document.createElement("button");
    // button에 "X"를 입력해줌.
    button.innerText = "X";
    
    // span을 li의 자식 element로 추가함. = li 내부에 span을 추가해줌
    li.appendChild(span);
    // button을 li의 자식 element로 추가함. = li 내부에 button을 추가해줌    
    li.appendChild(button);

    // HTML의 toDo-list에 li(내부에 span이 있는)를 자식 element로 추가해줌.
    toDoList.appendChild(li);
}

span btn 순서로 나타나짐

 

2.  eventlistener를 통해서 버튼에 상호작용을 만들어줌

   // button을 눌렀을 때 삭제가 되게하는 function
function deleteToDo() {


}
   
   
   
   // button에 click eventListner를 추가해줌.
    button.addEventListener("click", deleteToDo);

 

3. button이 여러개가 있을 때  button이 눌러진 것은 감지했지만, 어떤 버튼을 사용자가 눌렀는지 알아내야 함.

 

tip// 버튼을 구별하는 기준은 property의 parentNode, parentElement이다. 즉 버튼의 부모가 누구이냐는 것이다.

 

아래 사진을 통해서 각 버튼의 parentNode가 누구인지 알 수 있다.

위 사진에서 알 수 있듯이 버튼은 각자 다른 부모를 가지고 있는 것을 알 수 있다.

 

tip// 모든 HTML element 에는 하나 이상의 property가 있다. 그것은 바로 parentElement이다.

 

// button을 눌렀을 때 삭제가 되게하는 function
function deleteToDo(event) {
    // li는 클릭된 button의 부모 element이다. 즉 toDo이다.
    const li = event.target.parentElement;
    li.remove();
}

버튼을 누르기 전
버튼을 누른 후

 

 


 

 

Saving to Dos

 

핵심 : todo를 localstroage를 통해서 저장한다!

 

 

1. toDo를 저장한다.

1-1. toDos라는 array에 입력받은 todo를 저장한다.

const toDos = [];



function handleToDoSubmit(event) {
    // submit시 브라우저의 기본 동작인 새로고침 되는 것을 막아줌.
    event.preventDefault();
    // input value를 비우기 전에 그 값을 다른 변수에 저장해줌.
    const newTodo = toDoinput.value;
    toDoinput.value = "";
    
    // 입력받은 toDo를 array로 보내서 array에 저장한다.
    toDos.push(newTodo);

    // 인자로 입력받은 newTodo를 보냄.
    paintToDo(newTodo);
 
 // saveToDos function을 실행시켜줌.
    saveToDos();
}

1-2. array를 localstorage에 저장한다.

tip // localstorage에 배열을 저장할 수 없다. 오직 텍스트만 저장할 수 있음.

// toDos array의 내용을 localStorage에 넣는 function
function saveToDos() {
    localStorage.setItem("todos", toDos);
}

 

tip // JSON.stringify는 js object나 array  또는 어떠한 코드던 간에 그걸 string으로 만들어줌.

// toDos array의 내용을 localStorage에 넣는 function
function saveToDos() {
    localStorage.setItem(TODOS_KEY, JSON.stringify(toDos));
}

배열의 모양으로 저장됨.

 

 


 

 

Loading to Dos #part 1

 

핵심 : todo를 Load 할 수 있다.

 

tip // JSON.stringify는 js object나 array  또는 어떠한 코드던 간에 그걸 string으로 만들어줌.

tip // JSON.parse는 js object나 string 또는 어떠한 코드던 간에 그걸 array으로 만들어줌.

 

 

1. 모든 작업 후 toDos를 localStorage로 가져온다.

// "todos"를 TODOS_KEY로 바꿔줌
// localStorage로부터 TODOS_KEY("todos") 키값의 value를 가져옴.
const savedToDos = localStorage.getItem(TODOS_KEY);

 

 

 

2. 만약 savedToDos(키 값에 맞는 value)가 localStorage에 존재하면, 즉 null값이 아니라면 savedToDos(value)를 array로 바꿔줌.

tip // array에 있는 각각의 item에 대해서 fuction을 실행하는게 JS가 할 수 있는 일이다.

 

tip // forEach(function)는 array안의 각각의 item에 대해 function을 실행시킨다.

if(savedToDos !== null){
    const parsedToDos = JSON.parse(savedToDos);
    /*
    parsedToDos array에 있는 각각의 item에 대해서 function을 실행할 수 있게 해준다.
    */
    parsedToDos.forEach(function 이름);
}

 

 

 

3. array에 있는 각각의 item들을 이용할 수 있는 function을 만든다.

tip // 가장 중요한 것은 지금 처리되고 있는 item이 어떤 것인지 아는 것이다.

 

tip // submit eventListener가 event(argument)를 그냥 제공해 주는 것 처럼 

JS는 지금 처리되고 있는 item또한 argument로 그냥 제공해준다.

parsedToDos.forEach(sayHello);

function sayHello(item){
    console.log("this is the turn of", item);
}

위 코드를 짧게 쓸 수 있다. ( 화살표 함수 )

function sayHello(item){
	parsedToDos.forEach((item) => console.log("this is the turn of", item);
    }

 

 

 

 

 


 

 

 

Loading to Dos #part 2

 

핵심 : todo를 Load 할 수 있다.

 

 

1. parsedToDos array 내부에 저장된 item들을 화면에 표시

if(savedToDos !== null){
    const parsedToDos = JSON.parse(savedToDos);
    /*
    parsedToDos array에 있는 각각의 item에 대해서 function을 실행할 수 있게 해준다.
    */
    parsedToDos.forEach(paintToDo);
}

 

 

 

2. 아직 문제가 있는데, 새로고침하면 새로 추가한 value들만 저장되고, 예전 것들은 없어졌음.

즉 현재 새로운 것들이 추가 되는 것이아닌 예전 것들을 덮어 씌우고 있다.

새로고침하자 예전 것들은 사라진 모습

 

 

3. 위의 문제를 해결해보자

위의 문제가 일어난 이유는 application이 시작될 때 toDos array가 항상 비어있기 때문임.

 

. 해결 방법은 toDos array를 빈 값으로 시작하는 대신에 let으로 바꿔서 업데이트가 가능하게 만들고,

localStorage에 toDo 들이 있으면(null이 아니면), toDos에 parsedToDos를 넣어서 새로고침되더라도 전에 있던 toDo들을 복원한다.

 

// let으로 바꿔줌으로서 업데이트가 가능해지고, 더 이상 빈 값이 아니게 됨
let toDos = [];

if(savedToDos !== null){
    const parsedToDos = JSON.parse(savedToDos);
    // toDos에 parsedToDos를 넣음으로, 새로고침 되더라도 전에 값들이 남아있게 해줌.
    toDos = parsedToDos;
    /*
    parsedToDos array에 있는 각각의 item에 대해서 function을 실행할 수 있게 해준다.
    */
    parsedToDos.forEach(paintToDo);
}

 

이전 값들이 남아있는것을 확인 할 수있다.

 

이제 남은 문제는 삭제 button을 통해 삭제를 해도 localStorage에서 삭제 된 것은 아니므로, 새로고침하면 다시 복구되는 문제이다.

 

 

 


 

 

 

Deleteing To Dos part One

 

핵심 : button을 눌러서, localStorage에 저장된 toDos를 삭제할 수 있다.

 

tip // loaclStorage는 데이터베이스가 아니다. 그저 toDos array를 복사해두는 곳이다.

우리의 데이터베이스는 toDos array이다.

 

 

 

. toDos가 array형태로 있으면, 만약 같은 문자가 입력 받았을 때, 정확히 구별하여 삭제하기가 힘듦

그래서 toDos에게 ID 같은 것을 부여함으로서 같은 문자가 입력받아도 ID 값으로 분류하고자 함. 

 

1. text 대신에 object를 array에 push하도록 만듬.

tip // Date.now()는 밀리초를 주는 함수인데, 랜덤숫자같이 보임. 이 기능을 이용해 ID값을 부여할 것임

function handleToDoSubmit(event) {
    // submit시 브라우저의 기본 동작인 새로고침 되는 것을 막아줌.
    event.preventDefault();
    // input value를 비우기 전에 그 값을 다른 변수에 저장해줌.
    const newTodo = toDoinput.value;
    toDoinput.value = "";
    
    /* text대신 object를 만들어서 object안에 각 값들을 넣어주고
       object를 toDos array로 보내줌.
    */
    const newTodoObj = {
        text: newTodo,
        id: Date.now(),
    };
    toDos.push(newTodoObj);

    // 인자로 입력받은 newTodo를 보냄.
    paintToDo(newTodo);
    
    // saveToDos function을 실행시켜줌.
    saveToDos();
}

이제 단순한 text가 아닌 object 형태로 array가 만들어진 모습

 

 

 

2. paintToDo에 string으로 newTodo를 주는 것 대신에 object로 newTodoObj를 줌.

function handleToDoSubmit(event) {
    // submit시 브라우저의 기본 동작인 새로고침 되는 것을 막아줌.
    event.preventDefault();
    // input value를 비우기 전에 그 값을 다른 변수에 저장해줌.
    const newTodo = toDoinput.value;
    toDoinput.value = "";
    
    /* text대신 object를 만들어서 object안에 각 값들을 넣어주고
       object를 toDos array로 보내줌.
    */
    const newTodoObj = {
        text: newTodo,
        id: Date.now(),
    };
    toDos.push(newTodoObj);

    // 인자로 입력받은 newTodoObj를 보냄.
    paintToDo(newTodoObj);
    
    // saveToDos function을 실행시켜줌.
    saveToDos();
}

 

. 현재 문제는 글자를 적어서 submit하면 위 사진과 같이 [object Object]라고 출력이 됌. 우리는 실제 글자가  출력되게 만들것임

 

 

3. paintTodo를 바꿔준다. Cuz paintTodo가 이제는 text가 아닌 object를 인자로 받기 때문이다.

// submit된 newTodoObj를 매개변수로 받음
function paintToDo(newTodoObj) {
    // HTML에 li라는 element를 만들어줌
    const li = document.createElement("li");
    
    // HTML에 span이라는 element를 만들어줌
    const span = document.createElement("span");
    // span에 newTodo(입력받은 toDo)를 입력해줌.
    span.innerText= newTodoObj.text;
    
    // HTML에 button이라는 element를 만들어줌
    const button = document.createElement("button");
    // button에 "X"를 입력해줌.
    button.innerText = "X";
    // button에 click eventListner를 추가해줌.
    button.addEventListener("click", deleteToDo);

    // span을 li의 자식 element로 추가함. = li 내부에 span을 추가해줌
    li.appendChild(span);
    // button을 li의 자식 element로 추가함. = li 내부에 button을 추가해줌    
    li.appendChild(button);

    // HTML의 toDo-list에 li(내부에 span이 있는)를 자식 element로 추가해줌.
    toDoList.appendChild(li);
}

 

 

3. paintTodo()의 li에 id값을 부여해 각자 구별하고자 함. 

function paintToDo(newTodoObj) {
    // HTML에 li라는 element를 만들어줌
    const li = document.createElement("li");
    // li에 id값을 부여해줌.
    li.id = newTodoObj.id;

 

 

이제 다음 해결할 문제는 우리가 "X"를 누른 버튼의 id값을 얻어서 array에서 item을 삭제하는 것이다.

 

 

 

 


 

 

 

Deleteing To Dos part Two

 

핵심 : button을 눌러서, localStorage에 저장된 toDos를 삭제할 수 있다.

 

 

위 사진을 통해 알 수 있듯이 삭제 버튼을 눌러도 아직 localStorage에서 삭제가 되지않음.

 

tip // 만약 array에서 뭔가를 삭제할 때 실제로 array에서 그걸 지우는 것은 아님. 

진짜 일어나는 일은 지우고 싶은 item을 빼고 새 array를 만듦 = 지우고 싶은 item을 제외한다.

 

filter 함수를 사용하면 위의 일을 할 수 있음. filter는 filter 함수가 필요하다고 우리에게 요청함.

 

[1, 2, 3, 4].filter(sexyFilter);
 위의 코드의 의미는 JavaScript가 sexyFilter 각각의 1, 2, 3, 4를 부른다는 의미다.
 
 
// 위의 사진을 보면 알 수 있듯이
Filter 함수는 새로운 array에서도 입력 값들을 포함하고 싶으면 반드시 true를 리턴해야 함.
반대로 false를 리턴하면 그 값은 새 array에 포함되지않음.
 
 
 
 

. array의 모든 item를 유지하는 함수를 만들기 위해서는 true를 반환해주면 되고,

특정 item만 제거 하고싶으면 조건식을 통해 해당 item만 false를 반환해주면 된다.

 

 

. array의 각 item이 filter function의 첫번째 argument가 된다. 즉 sexyFilter(매개변수) 매개변수는 어떠한 단어를 써도 괜찮다.

 

 

 

 


 

 

 

Deleteing To Dos part Three

 

핵심 : button을 눌러서, localStorage에 저장된 toDos를 삭제할 수 있다.

 

 

. filter function은 예전 array에서 작업을 하는 것이 아닌 새 array를 준다.

 

 

 

1. 클릭했던 li의 id를 갖고있는 toDo를 지운다. 즉 클릭한 것을 제외하고 남기고 싶음.

// button을 눌렀을 때 삭제가 되게하는 function
function deleteToDo(event) {
    // li는 클릭된 button의 부모 element이다. 즉 toDo이다.
    const li = event.target.parentElement;
    li.remove();
    // 우리가 클릭한 li.id와 다른 toDo는 남기고 싶음.
    // li.id는 string이기 때문에 int형으로 변환해줌.
    toDos = toDos.filter((newTodo) => newTodo.id != parseInt(li.id));
    // toDos array가 새로 바뀌었기 때문에 saveToDos를 localStorage에 새로 저장함.
    saveToDos();
}

 

 

 

 

 

 

 

 

 

 

 

 

 

 


 

 

 

핵심 요약

1. 입력 후 Enter를 누를 때 마다 입력한 것을 비우고 싶을 때 value에 빈 값("")를 넣어주면 됌.

 

2. span은 div와 다르게 줄바꿈이 되지않는다.

 

3. append는 항상 마지막에 위치해야 함.

 

4. 누른 버튼을 구별하는 기준은 property의 parentNode, parentElement이다. 즉 버튼의 부모가 누구이냐는 것이다.

 

5. 모든 HTML element 에는 하나 이상의 property가 있다. 그것은 바로 parentElement이다.

 

6. localstorage에 배열을 저장할 수 없다. 오직 텍스트만 저장할 수 있음.

 

7. JSON.stringify는 js object나 array  또는 어떠한 코드던 간에 그걸 string으로 만들어줌.

 

8. JSON.parse는 js object나 string 또는 어떠한 코드던 간에 그걸 array으로 만들어줌.

 

9. 가장 중요한 것은 지금 처리되고 있는 item이 어떤 것인지 아는 것이다.

 

10. submit eventListener가 event(argument)를 그냥 제공해 주는 것 처럼 JS는 지금 처리되고 있는 item또한 argument로 그냥 제공해준다.

 

11. 해결 방법은 toDos array를 빈 값으로 시작하는 대신에 let으로 바꿔서 업데이트가 가능하게 만들고,

localStorage에 toDo 들이 있으면(null이 아니면), toDos에 parsedToDos를 넣어서 새로고침되더라도 전에 있던 toDo들을 복원한다.

 

12. loaclStorage는 데이터베이스가 아니다. 그저 toDos array를 복사해두는 곳이다. 우리의 데이터베이스는 toDos array이다.

 

13. Date.now()는 밀리초를 주는 함수인데, 랜덤숫자같이 보임. 이 기능을 이용해 ID값을 부여할 것임

 

14.  만약 array에서 뭔가를 삭제할 때 실제로 array에서 그걸 지우는 것은 아님.  \진짜 일어나는 일은 지우고 싶은 item을 빼고 새 array를 만듦 = 지우고 싶은 item을 제외한다.

 

15. filter 함수를 사용하면 위의 일을 할 수 있음. filter는 filter 함수가 필요하다고 우리에게 요청함.

 

16. array의 모든 item를 유지하는 함수를 만들기 위해서는 true를 반환해주면 되고, 특정 item만 제거 하고싶으면 조건식을 통해 해당 item만 false를 반환해주면 된다.

 

17. array의 각 item이 filter function의 첫번째 argument가 된다. 즉 sexyFilter(매개변수) 매개변수는 어떠한 단어를 써도 괜찮다.

 

 

반응형

'FrontEnd' 카테고리의 다른 글

웹 프론트엔드란?  (0) 2022.01.03
동백 // 부트스트랩이란???  (0) 2021.11.09
동백 // 노마드 코더 바닐라JS: Quotes  (0) 2021.11.09
CSS 레이아웃 정리 display, position  (0) 2021.11.08