Leta Learns

To Do List 본문

JavaScript

To Do List

leta 2021. 8. 15. 17:06

 

자바스크립트 문법 

: 표준화된 스크립트 프로그래밍 언어인 ECMAScript를 따른다. 

  ECMAScript는 매년 조금씩 변경되고, ES6(2015)를 기준으로 많이 변경되었다.

 

 

ex) 변수 선언 후 두 수의 값 더하기

#ES5

var a = 10;
var b = 10;
function sum(x, y) {
	return x + y;
}
sum(a, b); // 20

var 키워드를 사용하여 변수 선언.

ES6으로 넘어가면서 var의 단점을 보완하고자 let과 const로 세분화 되었다.

 

#ES6

let name = 'javascript';
console.log(name); // javascript  (console.log: 파이썬의 print와 같은 역할)

name = 'react';
console.log(name); // react

-----------------------------

const name = 'javascript';
console.log(name); // javascript

name = 'react';
console.log(name); // Uncaught TypeError: Assignment to constant variable.

let: 내부 값이 바뀔 수 있는 선언 키워드

const: 내부 값이 변하지 않고 고정된 선언 키워드

=> 변수 재할당 가능 여부에 따라 let, const 분류

     재할당 가능 : let (변경될 여지가 있는 경우 사용)

              불가능 : const

 

 

 


 

 

 

 

버튼을 눌렀을 때 그 버튼과, 할 일, 삭제 버튼을 추가시키는 것 모두 자바스크립트가 하는 일.

 

 

index.html, styles.css, todo.js 세 파일을 만든 후 HTML, CSS 각각에 아래 내용을 추가한다.

 

index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8"/>
    <meta name="viewport" content="width=device-width, initial-scale=1.0"/>
    <title>To do list</title>
    <link rel="stylesheet" href="styles.css"/>
</head>
<body>
<section class="todo_wr">
    <h2>To Do List</h2>
    <form>
        <input type="text" class="todo_txt"/>
        <button class="btn_submit">추가</button>
    </form>
    <ul class="todo_list">
    </ul>
</section>
<script src="todo.js"></script>
</body>
</html>

 

styles.css

* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
  outline: 0;
}

li {
  list-style: none;
}

button {
  border: 0;
  background: none;
}

body {
  background-color: white;
  min-height: 100vh;
  margin: 0;
  display: flex;
  align-items: center;
  justify-content: center;
}

.todo_wr {
  border: 1px solid black;
  width: 375px;
  min-height: 500px;
  padding: 30px 40px;
  background-color: #fff;
  border-radius: 30px;
}

.todo_wr h2 {
  margin: 0 0 30px 0;
}

.todo_wr form {
  width: 100%;
  display: flex;
}

.todo_wr input {
  width: 80%;
  padding: 0 10px;
  margin: 0 3% 0 0;
  height: 40px;
  border: solid 1px #e1e2e3;
  border-radius: 5px;
  font-size: 16px;
}

.todo_wr .btn_submit {
  width: 20%;
  height: 40px;
  line-height: 40px;
  border: 0;
  background-color: black;
  border-radius: 5px;
  color: #fff;
}

.todo_wr h2 {
  text-align: center;
}

.todo_list {
  margin: 30px auto;
}

.todo_list li {
  width: 100%;
  height: 40px;
  display: flex;
  align-items: center;
  position: relative;
}

.todo_list li.on {
  color: #999;
  text-decoration: line-through;
}

.todo_list li .btn_check {
  width: 16px;
  height: 16px;
  margin: 0 10px 0 0;
  position: relative;
}

.todo_list li .btn_check:before {
  content: "";
  display: block;
  position: absolute;
  top: 0;
  left: 0;
  width: 16px;
  height: 16px;
  border: 1px solid #ccc;
  border-radius: 50%;
  box-sizing: border-box;
}

.on > .btn_check {
  background: #7370d3;
  border: 0px solid #ccc;
  border-radius: 50%;
}

.todo_list li .btn_del {
  width: 16px;
  height: 16px;
  margin: -8px 0 0 0;
  position: absolute;
  top: 50%;
  right: 10px;
  background: url(https://cdn.iconscout.com/icon/free/png-256/delete-844-902124.png)
    no-repeat 100% 100%;
  background-size: contain;
}

 

 

HTML, CSS 파일을 완성한 후 브라우저를 열어보면 HTML 파일은 나타나지만 이벤트 처리는 되어있지 않다.

이렇게 정적인 HTML에 JS를 사용하여 동적인 이벤트를 넣어줄 것이다.

 

JS는 HTML의 특정 클래스나 id를 변수로 받아와서 그 변수에 이벤트를 정의해주는 방식으로 진행한다.

getElementByld id 가져오기
getElementsByClassName 클래스 가져오기
querySelector id, 클래스 모두에 사용 가능

 

 

 

todo.js

const input = document.querySelector(".todo_txt");
const btn = document.querySelector(".btn_submit");
const todoList = document.querySelector(".todo_list");

index.html을 보면,

todo_txt : 값을 적을 input에 대한 클래스명

btn_submit : 값을 추가하는 버튼에 대한 클래스명

todo_list : 값들이 추가될 ul 태그에 대한 클래스명

 

 

 

todo.js (전체 코드)

const input = document.querySelector(".todo_txt");
const btn = document.querySelector(".btn_submit");
const todoList = document.querySelector(".todo_list");

const addTodo = (e) => {
  e.preventDefault();
  if (input.value.trim().length < 1) {
    return;
  }

  const list = document.createElement("li");

  const btnChk = document.createElement("button");
  btnChk.setAttribute("class", "btn_check");
  btnChk.addEventListener("click", (e) => {
    const chkList = e.target.parentElement;
    chkList.classList.toggle("on");
  });

  const btnDel = document.createElement("button");
  btnDel.setAttribute("class", "btn_del");
  btnDel.addEventListener("click", () => {
    todoList.removeChild(list);
  });

  todoList.appendChild(list);
  list.appendChild(btnChk);
  list.insertAdjacentHTML("beforeend", `${input.value}`);
  list.appendChild(btnDel);
  input.value = "";
};

btn.addEventListener("click", addTodo);
input.addEventListener("keypress", (e) => {
  if (e.key === "Enter") {
    addTodo();
  }
  return;
});

#화살표 함수

ES6을 통해 도입된 함수.

기존에는 아래와 같은 형태.

function addTodo() {
  (..)
}

화살표 함수를 사용함으로써 명시적으로 변환을 할 수 있게 되고, 코드가 간결해진다. (파이썬의 def와 동일)

 

 

 

 

todo.js의 전체 코드를 이해하기 위해 파트를 나누어서 상세히 설명할 것.

 

 

todo.js

e.preventDefault();
  if (input.value.trim().length < 1) {
    return;
  }

e.preventDefault() : 기존에 각 개체가 가진 기본 성질을 무시하겠다는 뜻.

                          ex) submit 타입의 input이나 버튼을 누르면 페이지 새로고침.

                               우리가 적은 할 일(to do list)를 추가하는 과정에서 버튼을 눌러야 하기 때문.

                               이때 e.preventDefault()가 없으면 버튼을 눌렀을 때 새로고침은 되지만 값은 추가되지 않는다.

 

아래의 if문은 .todo-txt를 가져온 input 값이 아무것도 없을 경우 아무 일도 일어나지 않게끔 만드는 것.

input.value를 통해 input에 작성한 값을 가져온 후, trim()을 이용하여 공백을 제거한다.

=> 공백만 있는 경우 or 아무것도 없는 경우 : 아래에 나올 코드들이 하나도 실행되지 않도록 return

 

 

 

todo.js

  const list = document.createElement("li");

  const btnChk = document.createElement("button");
  btnChk.setAttribute("class", "btn_check");
  btnChk.addEventListener("click", (e) => {
    const chkList = e.target.parentElement;
    chkList.classList.toggle("on");
  });

createElement : 지정한 태그의 HTML 요소를 만들어 반환.

                     list 변수를 무엇인가를 추가하는 역할을 가진 API와 함께 쓴다면 새로운 li 태그가 추가된다.

                     버튼을 눌렀을 때, 새로운 값이 li 형태로 추가되는 것을 의미.

 

setAttribute : Element.setAttribute(name, value) 의 형태로 쓰인다. (name: 속성 이름, value: 속성값)

                 

                  btnChk.setAttribute("class", "btn_check"); 

                  => 새 버튼을 만드는 변수인 btnChk에 btn_check라는 변수를 부여하는 것.

                       btnChk가 추가되는 이벤트가 발생할 경우

                       <button class='btn_check'></button>의 형태로 버튼이 만들어진다.

 

addEventListener : 지정한 이벤트(type)가 대상(target)에 전달될 때마다 호출할 함수를 설정하는 API

                         주로 target.addEventListener(type, listener)의 형태로 사용된다.

                         => type : 키보드 누르기, 클릭 등의 이벤트 타입

                              listener : 함수

 

                         btnChk 라는 버튼을 클릭했을 때, 새로운 변수에 e.target.parentElement 라는 API 지정.

                             -> btnChk 버튼을 클릭할 때마다 클래스에 "on"이라는 이름이 추가, 삭제를 반복 (toggle)

 

e.target.parentElement : btnChk가 들어갈 위치의 부모 요소를 지칭.

                                (노션 확인하기)

 

 

 

 

todo.js

  const btnDel = document.createElement("button");
  btnDel.setAttribute("class", "btn_del");
  btnDel.addEventListener("click", () => {
    todoList.removeChild(list);
  });

 

(list, btnChk와 마찬가지)

createElement : btnDel을 버튼을 만들어주는 변수로 지정

 

setAttribute : 새롭게 만들어질 삭제 버튼에 btn_del이라는 클래스가 들어가도록.

 

addEventListener : 이 버튼을 클릭했을 때 todoList의 해당 값이 사라지도록.

 

list 별로 체크 버튼과 삭제 버튼을 넣기 때문에 해당 삭제 버튼이 들어가있는 li 태그만 삭제된다.

 

.removeChild : 자식 요소 값을 지우는 API.

                    ul 태그인 todoList의 자식 요소인 list(li 태그)를 지우겠다는 뜻.

 

 

 

 

todo.js

  todoList.appendChild(list);
  list.appendChild(btnChk);
  list.insertAdjacentHTML("beforeend", `${input.value}`);
  list.appendChild(btnDel);
  input.value = "";
};

todoList.appendChild(list); : todoList라는 변수로 지정한 ul 태그에 list라는 변수로 지정한 li태그를 추가.

 

.appendChild : ul 태그의 자식요소로 li 태그를 추가한다. (like .removeChild)

 

list라는 변수로 선언한 li 태그 안에 btnChk로 선언한 체크 버튼과 btnDel로 선언한 삭제 버튼을 넣는다.

더보기

<ul class="todo_list>

    <li>

        <button class="btn_check"></button>

            내용

        <button class="btn_del"></button>

    </li>

</ul>

 

insertAdjacentHTML : 특정 근접 위치에 HTML을 삽입하는 API

                             element.insertAdjacentHTML(position, text)와 같은 형태로 사용.

                                 (position에 text가 들어가는 형태)

                                 position에 들어갈 수 있는 4가지

                                      beforebegin : element 앞

                                      afterbegin : element 안에 가장 첫 번째 child

                                      beforeend : element 안에 가장 마지막 child

                                      afterend : element 뒤

 

현재 element로 삼은 list에는 체크 버튼과 삭제 버튼이 들어있고, 체크 버튼과 삭제 버튼 사이에 todoList에서 입력한 텍스트가 들어가야 한다.

=> 삭제 버튼을 넣어주기 전에 insertAdjacentHTML API를 사용해 input의 value 값을 먼저 넣어준 것.

     (input의 value 값 : index.html에서 todo_txt)

 

여기까지하면 함수 끝 => 체크 버튼과 삭제 버튼을 가진 li 태그 생성.

 

할 일을 입력하고 버튼을 누르면, 기존에 입력한 값은 삭제해줘야 하므로 input.value = ''; 를 통해 값을 비워준다.

 

 

 

 

todo.js

btn.addEventListener("click", addTodo);
input.addEventListener("keypress", (e) => {
  if (e.key === "Enter") {
    addTodo();
  }
  return;
});

btn.addEventListener("click", addTodo); : btn_submit 클래스를 변수로 받아온 btn에 대해 클릭했을 때

                                                     addTodo 함수를 실행하겠다는 뜻.

                                                     addTodo 함수를 만들어도 이 함수를 실행하겠다는 명령이 없으면 실행 x

 

input.addEventListener("keypress", (e) ~ : keypress 이벤트를 했을 때, 즉 키보드를 눌렀을 때 아래 부분이

                                                      실행되게 하는 이벤트 실행 함수.

                                                      e.key == "Enter"

                                                         => 엔터키를 눌렀을 때 addTodo 함수 실행

 

if문 바깥의 return : 다른 키를 누른 경우 실행 x (여기서는 크게 중요하지 않음)

 

 

 

 

 

todoList 구현 영상

 

Comments