Web -front/HTML,CSS,JS
예제 만들면서 배우기 4. Hello world 급 예제 Todolist 만들기.
초보개발자뀨
2021. 3. 13. 09:14
예제 택한 이유
- 이번 예제는 앞선 예제를 하면서 배운 것들로 프론트 예제로 가장 흔하고 많이 한다는 TodoList를 만들어 보았습니다.
구현한 기능
- 플러스 버튼 누를시 Prompt 창을 활성화시켜 텍스트를 입력시키면 추가된다.
- 삭제
- 수행한 일을 체크하고 체크된 메모 삭제하면 체크된 메모들 삭제
- 가장 마지막에 입력한 메모 삭제
- 모든 메모 삭제
- 저장
- 본래 저장은 네트워크를 이용해 db를 연동해 하고싶었지만.. 어려움을 느껴 우선 로컬 스토리지를 이용해 메모를 이용하는 사용자에게만 해당 메모가 보이도록했다. 인터넷 기록을 삭제하지 않는 한 남아있도록 했다.
더 구현 하고 싶은 기능
- DB를 이용하여 사용자 별로 정리하기
- Node.js를 이용하여 하고 싶었지만 벽에 느껴.. 좀 더 공부하고 다시 도전해야할듯 싶다.. 서버는 아직 공부가 많이 필요한것같다.
- 해당 메모 클릭 시 수정 가능
- 중요도별로 메모 목록화 하기
어려웠던 점
1.일단은 레이아웃이 제일 어려웠다.. 원하는대로 배치되는게 별로 없었다. 이를 통해 많이 배웠다
2.자바 스크립트에서 삭제 함수를 짤 때 내가 지우고자하는 위치의 아이템의 인덱스를 어떻게 얻어오는지 몰라 많이 고생했고 검색을 통해서 해결하였다.
Main.html
개선되어야 할 점(단톡방 피드백)
- let의 무분별 사용! 다시 재할당 안할 변수라면 const를 사용하자
- 재할당이란 쉽게 말해 let a=1; a=2; 이런식으로 변수에 다시 값을 주는 경우
- es6 문법 사용
- for문도 좋지만 다양한 배열메소드의 사용 권고 (ex map,filter , forEach)
- 비교연산자 동등연산자 구별해서 사용
- 컨벤션 통일 변수명 등 카멜표기법을 통일해서 사용하자
Main.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="preconnect" href="https://fonts.gstatic.com">
<link href="https://fonts.googleapis.com/css2?family=Sunflower:wght@300&display=swap" rel="stylesheet">
<script src="https://kit.fontawesome.com/012d5a0fd2.js" crossorigin="anonymous"></script>
<link rel="stylesheet" href="Main.css">
<title>Document</title>
</head>
<body>
<div class="context">
<div class="head">
<h1>TodoList!</h1>
<div class="insert">
<i id =" btn_insert" class="fas fa-plus-circle" onclick="input()"></i>
</div>
</div>
<div id ="do_list" class="do_list">
</div>
<div class="remove">
<button onclick="remove_select()">체크된 메모 삭제!</button>
<button onclick="remove_lastItem()">마지막 메모 삭제</button>
<button onclick="remove_all()"> 모든 자료 삭제</button>
</div>
</div>
<script src="Main.js"></script>
</body>
</html>
Main.css
body{
font-family: 'Sunflower', sans-serif;
background-color: rgb(63, 63, 63);
}
.context {
border-radius: 10px;
margin : auto;
height: 800px;
width: 500px;
}
.head {
color: #f4f9f9;
border-top-left-radius: 10px;
border-top-right-radius: 10px;
display: flex;
flex-direction: column;
background-color: #a4ebf3;
text-align: center;
width: 100%;
height: 120px;
}
.insert{
width: 480px;
margin-bottom: 10px;
justify-content: center;
margin-top: auto;
display: flex;
}
.insert i{
color: white;
background-color: #a4ebf3;
width: 30px;
height: 30px;
font-size: 30px;
}
.insert input{
width: 280px;
}
.do_list{
overflow :auto;
background-color: #f4f9f9;
width: 100%;
height: 650px;
color: #f4f9f9;
display: flex;
flex-direction: column;
}
.memo{
border-radius: 10px;
padding-top: 5px;
padding-bottom: 5px;
background-color: #f4f9f9;
justify-content: space-around;
margin: 10px 10px 5px 5px ;
display: flex;
height: 39px;
align-items: center;
box-shadow: 2px 2px 2px 2px rgb(173, 173, 173);
}
.memo div{
color: black;
margin-top: 5px;
font-weight: bold;
font-family: 'Sunflower', sans-serif;
width: 400px;
resize: none;
border :none;
background-color: #f4f9f9;
font-size: 20px;
height: 30px;
}
#checkbox{
height: 15px;
zoom: 1.5;
}
.remove{
border-bottom-left-radius: 10px;
border-bottom-right-radius: 10px;
padding: 5px;
height: 50px;
background-color: #a4ebf3;
display: flex;
justify-content: space-evenly;
}
.remove button{
border-radius: 15px;
font-family: 'Sunflower', sans-serif;
font-weight: bold;
}
@media(min-width: 320px) and (max-width: 480px){
.context{
width: 400px;
}
.insert {
text-align: center;
color: white;
background-color: #a4ebf3;
width: 100%;
height: 30px;
font-size: 30px;
}
}
Main.js
const btn_input = document.getElementById('.btn_input');
const do_list = document.getElementById('do_list');
let text_list =[];
window.addEventListener("keydown",(e)=>{
if(e.keyCode==13) input();
});
if(localStorage.getItem('memo')!=null){
print();
}
function input(){
let text = prompt("할 일을 입력해주세요!");
if(text!=null){
let row =
`<div class="memo">
<input type="checkbox" name="checkbox" id="checkbox">
<div >${text}</div>
</div>
`;
do_list.innerHTML +=row;
text_list.push({'memo' : text});
localStorage.setItem('memo',JSON.stringify(text_list));
}
}
function remove_lastItem(){
let list = document.querySelectorAll('.do_list > div');
let liLen = list.length-1;
let remove_confirm = confirm("정말로 삭제 하시겠습니까?");
if(remove_confirm) {
do_list.removeChild(list[liLen]);
text_list.splice(liLen,1);
replace();
}
}
function remove_select(){
let memo_list =document.querySelectorAll('.do_list>div');
let checkbox_list = document.querySelectorAll('.do_list > div >#checkbox');
let liLen = checkbox_list.length-1;
let remove_confirm = confirm("정말로 삭제 하시겠습니까?");
if(remove_confirm) {
for(let i =liLen ; i>=0;i--){
if(checkbox_list[i].checked==true) {
text_list.splice(i,1);
do_list.removeChild(memo_list[i]);
}
}
replace();
}
}
function remove_all(){
let remove_confirm = confirm("정말로 삭제 하시겠습니까?");
if(remove_confirm) {
do_list.innerHTML ="";
localStorage.removeItem('memo');
}
}
function print(){
text_list= JSON.parse(localStorage.getItem('memo'))
console.log(text_list);
for(let i = 0 ; i<text_list.length ;i++){
let text = text_list[i].memo;
let row =
`<div class="memo">
<input type="checkbox" name="checkbox" id="checkbox">
<div >${text}</div>
</div>
`;
do_list.innerHTML +=row;
}
}
function replace(){
localStorage.removeItem('memo');
localStorage.setItem('memo',JSON.stringify(text_list));
}