JS - todoList 본문
잠깐 HTML, ul태그와 ol태그의 차이
<ul>
<li>ul</li>
<li>Unordered List</li>
</ul>
<ol>
<li>ol</li>
<li>Order List</li>
</ol>
종속 태그로는 둘다 li 태그 사용
DOM(document object model)
브라우저가 HTML 문서를 파싱하는 과정에서 생겨나는 객체
아래처럼 나무와 비슷하게 생긴 모양 때문에 트리 구조라고 함
그리고 각각의 나뭇잎처럼 생긴 요소들은 노드라고 함
그리고 이 노드들은 객체 형태를 띔
onkeydown()
키보드가 눌릴 때마다 실행시켜줌
<input
type="text"
id="todo-input"
onkeydown="keyCodeCheck()"
/>
--
const keyCodeCheck = function () {
console.log(window.event.keyCode === 13)
if(window.event.keyCode === 13){
const inputValue = document.querySelector("#todo-input").value
console.log(inputValue)
}
}
// '엔터'의 keyCode === 13
createElement 로 노드 생성 및 appendChild로 하위 속성 추가
// createElement = 노드 생성
const newLi = document.createElement('li')
const newSpan = document.createElement('span')
// appendChild = 하위 속성으로 추가
newSpan.textContent = todoInput.value;
newLi.appendChild(newSpan)
todoList.appendChild(newLi)
노드 생성은 상위 요소에서 하위 요소 순으로,
하위 속성 추가는 하위 요소에서 상위 요소 순으로 해야 헷갈리지 않는다
완성한 뒤, input내에 값을 입력하고 엔터를 누르면, 작성한 값이 아래에 추가됨을 확인할 수 있음
이제 '할 일'과 '한 일'을 구분하기 위한 작업이 필요
// 버튼 노드 추가
const newBtn = document.createElement('button')
// 버튼에 이벤트 리스너 추가
// '버튼' '클릭' 시, 'newLi'에 class="coplete" 를 부여하겠다는 의미
newBtn.addEventListener('click', ()=> {
newLi.classList.toggle('complete')
})
// 그리고 만들어진 버튼을 'newLi'에 요소로 추가
newLi.appendChild(newBtn)
이후 '버튼'과 'complete'에 css 요소를 추가하면
아래와 같은 화면을 만들 수 있게 됨
리스트 삭제하기
// HTML 내 버튼 만들기
<div class="delete-btn-wrapper">
<button onclick="deleteAll()">전체 삭제</button>
</div>
--
// js 내 삭제 펑션
const deleteAll = function () {
const liList = document.querySelectorAll('li')
for(let i = 0; i<liList.length ; i++){
liList[i].remove()
}
}
HTML 버튼에 클릭 시 deleteAll() 실행하도록 함
deleteAll()은, 'li'를 가진 모든 요소를 불러다가 삭제
스토리지에 저장
먼저, 저장하기 위한 function을 만듬
const saveItemsFn = function () {
const saveItems = [];
for(let i = 0 ; i < todoList.children.length; i++) {
const todoObj = {
contents : todoList.children[i].querySelector('span').textContent,
complete : todoList.children[i].classList.contains('complete')
}
saveItems.push(todoObj)
}
console.log(saveItems, 'saveItems')
}
저장할 요소들을 todoObj에 객체화하여, 저장하게 되는데 이 때,
contents : 각 span 이 지니고 있는 textContent
complete : 는 각각의 li가 class="complete"를 가지고 있는 여부(contains)를 판단하여 true / false로 반환해줌
그리고, 객체 todoObj 를 배열 saveItem 안에 넣어주는 과정으로 해당 데이터를 저장
-- 잠깐 살펴봐야 할 개념
호이스팅
'함수 선언문'에서는 호이스팅이 발생하는데, 함수 발생 이전에 해당 함수가 스크립트 맨 위로 끌어올려진 것 같은 효과를 냄
그말인즉슨, 이는 스크립트 내에서 예상하지 못하는 동작을 할 가능성이 높기 때문에 사용을 지양하는 것이 좋음
추가적으로 var 역시 호이스팅이 발생함
스코프
- 전역 스코프 : 스크립트 전역에 선언된 변수 / 어디서든 참조 가능
- 지역 스코프 : 함수 내에 선언된 변수 / 함수 내에서만 참조 가능
let / const , var 사이의 가장 큰 차이점 중 하나는 스코프와 관련이 있음
let / const 는 '블록 스코프, 함수 스코프'라는 특징을 가지고 있는데,
블록 스코프는, 함수 안에서 선언된 let / const 의 경우 함수 안에서만 처리될 수 있다는 의미를 지니고 있음
반대로 var는 '함수 스코프'라는 특징만을 가지고 있기 때문에 호이스팅이 발생할 수 있는 것임
따라서, 예측 가능한 코드 작성을 위해서는 let / const 를 통해 변수를 선언하거나 함수 선언문을 통해 선언하는 것이 더 적절함
다시, 로컬 스토리지
로컬 스토리지에는 문자열로 저장해야 함
이때 배열은 String 함수를 통해 문자열화 시켜줄 수 없음
이러면 JSON이라는 데이터 포맷을 활용해줘야함
JSON.stringify(saveItems)
'JSON' 포멧을 활용하여, '문자열화' 해줌 이라는 의미
이를 콘솔값 JSON.stringify(saveItems) 으로 뽑아내면 아래와 같은 값을 얻을 수 있음
원하는 값을 얻었으니 로컬 스토리지에 저장하면 됨
localStorage.setItem('saved-items', JSON.stringify(saveItems))
그러면, 위와 같은 형태로 객체가 로컬 스토리지에 저장됨을 확인할 수 있음
이후 페이지를 열 때마다 저장된 요소를 꺼내오기 위해 최상단에 저장된 객체를 불러옴
const savedTodoList = JSON.parse(localStorage.getItem("saved-items"))
// 이때 JSON.parse 는 위에 저장하기 위해 stringify해준 것을 원래대로 돌려놓기 위함
그리고 가져온 데이터를 다시 구현하기 위해 최하단에 위와 같이 작성
// createTodo 호이스팅 때문에 맨 아래로 내려주었음
if(savedTodoList){
for(let i=0; i<savedTodoList.length; i++) {
createTodo(savedTodoList[i])
}
}
이후 저장된 데이터가 있다면, 저장된 컨텐츠를 todoContents에
입력된 값이 있다면, todoContents로 할당
어쨌든 todoContents라는 변수로 처리되고 있기 때문에 상관없음
const createTodo = function (storageData) {
let todoContents = todoInput.value
if(storageData){
todoContents = storageData.contents
}
추가로 받아온 객체의 complete 값이 true 라면,
기존에 만든 complete 클래스를 추가해줌
// 옵셔널 체이닝
if(storageData?.complete) {
newLi.classList.add('complete')
}
이때 storageData?.complete 는 두가지를 묻는 것임
- storageData 가 truly 인가?
- storageData 가 truly라면, stroageData.complete가 true인가?
위와 같은 표현 방식을 옵셔널 체이닝이라고 함
마지막 저장된 데이터가 없을 경우 모두 삭제 / 그렇지 않다면 save-item 저장
saveItems.length === 0
? localStorage.removeItem('saved-items')
: localStorage.setItem('saved-items', JSON.stringify(saveItems))
'개발 > JavaScript' 카테고리의 다른 글
JS - reduce 메서드 / 논리연산자 / 단축평가 (0) | 2022.12.31 |
---|---|
JS - todolist / 날씨 적용하기(API) (0) | 2022.12.30 |
JS - 배열 안 객체 활용하기 (1) | 2022.12.29 |
JS - 반복문(for, while) / 객체활용 for문 / for in / for out (0) | 2022.12.28 |
JS - 함수 / 함수 사용 (1) | 2022.12.27 |