이전에 작업을 하면서 main-container 에 이미 우리는 userInfo라는
페이지가 있습니다. 아직 우리는 페이지에 관해서 주소에 관한 개념이 없다고
가정하에 페이지를 완성하고 있습니다.
그렇기 때문에 같은 container 로 작업을 하되 hidden css를 따로 주어
javascript에서 제어를 해보도록 하겠습니다.
첫번째 input에 todo 를 적으면 todo가 작성한 시간으로 하나씩 생성
두번째 생성된 투두는 update 버튼과 delete버튼을 두어 각각 가능해야함
일단 눈에 보이는 기능은 두가지입니다.
index.html 부터 가보도록 하겠습니다.
<main class="main-container main-hidden">
<header class="main-header">
<h1 class="main-title">ToDo</h1>
<div class="todo-input-container">
<i class="fa-regular fa-file-lines"></i>
<input type="text" class="todo-input" placeholder="Please Enter To Do...">
<button class="add-todo-button"><i class="fa-solid fa-plus"></i></button>
</div>
</header>
<ul class="todo-content-list">
</ul>
</main>
매우 간단한 코드입니다.
input으로 받은 값을 ul태그 안에 li로 동적으로 생성하기 위해서
html로 고정해놓는 것이 아니라 javascript를 통한 생성을 할 것입니다.
class TodoEvent {
static #instance = null;
static getInstance() {
if(this.#instance == null){
this.#instance = new TodoEvent();
}
return this.#instance;
}
addEventAddTodoClick() {
// todo를 추가하는 클릭버튼을 눌렀을 때 행동하는 로직입니다.
const addTodoButton = document.querySelector('.add-todo-button');
addTodoButton.onclick = () => {
TodoService.getInstance().addTodo();
const todoInput = document.querySelector('.todo-input');
todoInput.value = '';
}
}
addEventAddTodoKeyUp() {
// 버튼대신 key 즉 enter키를 눌렀을 경우의 로직입니다.
const todoInput = document.querySelector('.todo-input');
todoInput.onkeyup = () => {
if(window.event.keyCode == 13) {
const addTodoButton = document.querySelector('.add-todo-button');
addTodoButton.click();
}
}
}
addEventRemoveTodoClick() {
// todo가 생성이된 후 삭제를 시키는 버튼을 눌렀을 때 로직입니다.
const removeButtons = document.querySelectorAll('.content-footer .remove-button');
removeButtons.forEach((removeButton, index) => {
removeButton.onclick = () => {
ModalService.getInstance().showRemoveModal(index);
}
});
}
addEventModifyTodoClick() {
// todo가 생성이 된 후 수정하는 버튼을 눌렀을 때 로직입니다.
const modifyButtons = document.querySelectorAll('.content-footer .modify-button');
modifyButtons.forEach((modifyButton, index) => {
modifyButton.onclick = () => {
ModalService.getInstance().showModifyModal(index);
const modalModifyContent = document.querySelector('.modal-modify-content');
const contents =TodoService.getInstance().todoList[index].todoContent;
modalModifyContent.focus();
modalModifyContent.value = contents;
}
});
}
addEventModifyTodoKeyUp() {
// 버튼대신 enter키를 입력했을 경우입니다.
const todoInput = document.querySelector('.modal-modify-content');
todoInput.onkeyup = () => {
if(window.event.keyCode == 13) {
const modifyTodoButton = document.querySelector('.modal-ok-button');
modifyTodoButton.click();
}
}
}
}
class TodoService {
static #instance = null;
static getInstance() {
if(this.#instance == null){
this.#instance = new TodoService();
}
return this.#instance;
}
todoList = null;
constructor() {
// service 클래스가 생성될 당시에 이루어질 기능들이다.
// 로컬스토리지에 todoList라는 값이 null이면
// 새로운 배열을 생성해서 집어 넣어준다.
// 하지만 아닐 경우 로컬 스토리지에 있는 값을 json 을 변환하여
// todoList에 대입시켜준다.
if(localStorage.getItem('todoList') == null) {
this.todoList = new Array();
}else {
this.todoList = JSON.parse(localStorage.getItem('todoList'));
}
this.loadTodoList();
}
updateLocalStorage() {
// 로컬스토리지를 업데이트 하는 과정입니다.
localStorage.setItem('todoList', JSON.stringify(this.todoList));
this.loadTodoList();
}
addTodo() {
// todo를 더할 때 요일을 변환해야 하는데 그 로직이 convertDay의 로직입니다.
const todoInput = document.querySelector('.todo-input');
const nowDate = new Date();
// console.log(`년 : ${nowDate.getFullYear()}`);
// console.log(`월 : ${nowDate.getMonth()}`);
// console.log(`일 : ${nowDate.getDate()}`);
// console.log(`요일 : ${nowDate.getDay()}`);
// console.log(`시 : ${nowDate.getHours()}`);
// console.log(`분 : ${nowDate.getMinutes()}`);
// console.log(`초 : ${nowDate.getSeconds()}`);
const convertDay = (day) => {
return day == 0 ? '일' :
day == 1 ? '월' :
day == 2 ? '화' :
day == 3 ? '수' :
day == 4 ? '목' :
day == 5 ? '금' : '토';
}
const todoObj = {
todoDate: `${nowDate.getFullYear()}.${nowDate.getMonth() + 1}.${nowDate.getDate()}(${convertDay(nowDate.getDay())})`,
todoDateTime: `${nowDate.getHours()}:${nowDate.getMinutes()}:${nowDate.getSeconds()}`,
todoContent: todoInput.value
}
this.todoList.push(todoObj);
this.updateLocalStorage();
}
loadTodoList() {
// todoList를 화면에 로드 시켜주는 로직입니다.
// inner html 을 이용해서 todoList 배열을 반복을 돌면서
// 해당 배열안에 있는 object들을 빼내와서 값을 대입해서 li를 만들어 줍니다.
const todoContentList = document.querySelector('.todo-content-list');
todoContentList.innerHTML = ``;
this.todoList.forEach(todoObj => {
todoContentList.innerHTML += `
<li class="content-container">
<div class="content-header">
<div class="todo-date">${todoObj.todoDate}</div>
<div class="todo-date-time">${todoObj.todoDateTime}</div>
</div>
<div class="content-main">
${todoObj.todoContent}
</div>
<div class="content-footer">
<button class="modify-button">
<i class="fa-regular fa-pen-to-square"></i>
</button>
<button class="remove-button">
<i class="fa-regular fa-trash-can"></i>
</button>
</div>
</li>
`;
});
TodoEvent.getInstance().addEventRemoveTodoClick();
TodoEvent.getInstance().addEventModifyTodoClick();
// TodoEvent.getInstance().addEventModifyTodoKeyUp();
}
}
동적으로 html 코드가 변화하고 생성되어야 하기 때문에 inner html 을 사용하고
배열에 input으로 들어오는 값들을 저장하여 반복을 돌려서 화면에 뿌려주는 형식입니다.
순수 자바스크립트를 이용해서 만들면서 귀찮은 코드들도 꽤나 많았던 것 같고
분명 반복을 처리하고 있는데 그안에 반복들이 있는 이상한 코드들도 꽤나 많았던 것 같다.
리액트로 변환하면서 새로운 라이브러리들과 달라지는 부분들을 소개해볼까 합니다.