리액트 하다가 갑자기 Vanilla JS TODOLIST .. ?
방학 막바지 8월에 들어오면서 공부를 진짜 해야겠다는 생각이 들었다. 그래서 내가 어떤 점이 모자른지 생각을 해보았다.
나는 리액트를 해왔지만, 하면서 항상 느낀점은 " 역시 기초가 중요하다. " 였다.
왜냐하면, 리액트를 사용해서 프로젝트를 진행하는 것에는 익숙했지만, 기본적인 JS 활용력이 떨어지다보니 순수 js 만 사용하여 프로젝트를 하기에는 모자른 실력이였다.
또, 요즘 오랑우톡 개발이 잠깐 막혀서.. ㅠㅠ 할 게 없어져 현타가 하루에 50번씩 왔었다.
백엔드가 CRUD 가 기본이라면 프론트는 TODOLIST 가 기본인 법.
가볍게 UI 부터 생각을 했다.
피그마로 UI 라도 좀 짤까 하다가 어차피 혼자 하는거니까 머릿속으로 대충 UI를 짜고 바로 개발에 들어갔다.
< UI 생각할 때 참고했던 window todolist >
< UI 생각할 때 참고했던 Momentum >
그리고 그냥 생각한대로 대강 퍼블리싱 완료!
이 정도까지 하고, 바로 input 을 만들고 이벤트 처리를 해주었다.
<input id="input-box" onkeyup=enter()
type="text" placeholder="오늘 할 일을 적어보세요.">
< index.html >
onkeyup
이벤트가 일어난다. // input 가져오기
const inputValue = document.querySelector('#input-box');
// 엔터 이벤트가 일어날 때 함수
const enter = () => {
if (window.event.keyCode == 13 && (inputValue.value)) {
toDo();
}
}
< index.js >
enter 키가 눌리고, input 안에 값이 있으면 toDo() 가 실행되도록(input 에 내용이 없으면 엔터가 눌렸더라도 toDo 함수 실행이 안 되도록 처리) 해주었다.
이렇게 해서 input 값을 js로 가져오고 엔터키를 눌렀고, input 안에 값이 있으면 toDo 함수를 실행하는 부분까지 완료되었다.
<main>
<input id="input-box" onkeyup=enter() type="text"
placeholder="당신의 오늘 할 일을 적어보세요.">
<div id="main-div">
</div>
</main>
< index.html >
// toDo 리스트를 추가하는 함수
const toDo = () => {
// input 에 들어온 text 설정
let text = inputValue.value;
// 새로운 tododiv 만들기
const newTodo = document.createElement("div");
const newTodoText1 = document.createElement("p");
const newTodoText2 = document.createElement("p");
// div 안에 자식 추가
newTodo.appendChild(newTodoText1);
newTodo.appendChild(newTodoText2);
// p 안의 text 설정
newTodoText1.innerHTML = `${text}`
// p 안의 del 설정
newTodoText2.innerHTML = 'X'
// class 추가
newTodo.setAttribute("class","todo-box");
newTodoText2.setAttribute("onclick","del()")
// mainDiv 안에 넣기
mainDiv.appendChild(newTodo);
// input 값 초기화
inputValue.value = '';
}
< index.js >
일단 input
에 들어온 text
를 저장해준다.
그리고 todo가 하나 추가될 때마다 html
에 새로운 tododiv
가 만들어져야하기 때문에 tododiv
를 만든다.
tododiv
에는 div 1개, 그리고 div 의 자식요소로 p 태그 2개가 들어가므로, 다음과 같이 적어준 것이다.
const newTodo = document.createElement("div");
const newTodoText1 = document.createElement("p");
const newTodoText2 = document.createElement("p");
<div>
<p></p>
<p></p>
</div>
appendChild
를 사용하여 div 의 자식으로 p 태그 두 개를 넣어준다. // div 안에 자식 추가
newTodo.appendChild(newTodoText1);
newTodo.appendChild(newTodoText2);
innerHTML 을 사용하여 태그 안에 들어갈 글씨를 정해준다.
setAttribute
를 사용하여 태그에 클래스와 이벤트를 설정한다.
마지막으로 html
에 mainDiv 컨테이너에 생성된 div 를 자식요소로 넣어준 후, input 값을 초기화 해준다.
// p 안의 text 설정
newTodoText1.innerHTML = `${text}`
// p 안의 del 설정
newTodoText2.innerHTML = 'X'
// class 추가
newTodo.setAttribute("class","todo-box");
newTodoText2.setAttribute("onclick","del()")
// mainDiv 안에 넣기
mainDiv.appendChild(newTodo);
// input 값 초기화
inputValue.value = '';
const del = () => {
// todo 의 부모를 찾아서 todo 를 삭제
mainDiv.removeChild(event.target.parentNode);
// 요게 todo 하나
console.log(event.target.parentNode);
}
< index.js >
event.target
은 이벤트가 일어난 요소를 반환한다. 따라서 event.target
은 X글씨가 있는 p 태그를 반환한다.
우리가 하고 싶은 것은 X 글씨를 누르면 해당 tododiv 블록 하나가 삭제되는 것이기 때문에, X 글씨의 부모를 찾아준다.
tododiv
들이 들어가있는 mainDiv
를 선택한 후, mainDiv
의 자식들 (tododiv들) 중에서 del
이벤트가 일어난 것을 찾아 삭제한다.
/* --- 글씨체 import --- */
/* font-family: 'Montserrat', sans-serif; */
@import url('https://fonts.googleapis.com/css2?family=Montserrat:wght@100;200;300;400;500;600&display=swap');
/* --- 기본 글씨체 설정 --- */
html {
font-family: 'Montserrat', sans-serif;
font-weight: 300;
font-size: 15px;
overflow: hidden;
}
/* --- body height 설정 ---
body {
} */
#header-div {
top:0;
font-weight: 300;
font-size: 4rem;
height: 10vh;
text-align: center;
padding: 3% 0;
}
#main-div {
display: flex;
flex-direction: column;
overflow-y: scroll;
height: 60vh;
width: 720px;
margin: 0 auto;
}
#main-div::-webkit-scrollbar{
width: 5px;
}
#main-div::-webkit-scrollbar-thumb{
height: 5%;
background-color: rgba(104, 207, 211, 0);
border-radius: 10px;
}
#main-div::-webkit-scrollbar-track{
background-color: rgba(206, 206, 206, 0);
}
#footer-div {
/* background-color: rgb(214, 214, 214); */
width: 100%;
position: absolute;
bottom: 0;
}
#input-box {
font-size: 1.8rem;
font-weight: 100;
display: block;
margin: 0 auto;
width: 680px;
height: 50px;
border: none;
padding: 10px;
border-bottom: 1px solid rgba(104, 207, 211, 0.8);
margin-bottom: 30px;
}
#input-box:focus {
/* transition: .3s; */
/* height: 50px; */
outline: none;
}
.todo-box {
transition: .3s;
display: flex;
align-items: center;
justify-content: space-between;
font-size: 1.5rem;
font-weight: 100;
min-height: 80px;
/* height: 80px; */
margin: 5px 0;
padding: 5px 30px;
border-radius: 10px;
border: 1px solid rgba(206, 206, 206, 0.3);
background-color: rgba(228, 228, 228, 0.2);
}
.todo-box p:nth-child(2) {
font-size: 2rem;
font-weight: 500;
color: rgba(206, 206, 206, 0.3);
}
.todo-box p:nth-child(2):hover {
color: rgb(248, 114, 114);
transition: .3s;
cursor: pointer;
}
.todo-text{
padding-right: 10px;
}
< 더 자세한 코드는 GITHUB로 ... >
여기까지 완성이 되었다.
input 에 할 일을 적고 엔터를 치면 아래에 추가가 되고, 박스마다 있는 x 버튼을 누르면 해당 박스가 삭제된다.
해당 todo가 생성된 시간도 표시를 해두었는데 이 부분은 다음 포스팅에 todolist를 localStorage 에 저장하여 새로고침해도 todolist 가 날아가지 않도록 하는 과정에서 설명을 해야겠다.
정말 오랜만에 Vanilla JS 로 무언가를 만들다보니, 처음에는 감도 잘 안 잡히고 이거였나 저거였나 긴가민가 하면서 자신이 없었다. 근데 하다보니 또 슬금슬금 재밌어지더라..^^ 열심히 완성해보자.
다음은 무얼 하시나용?🤔