728x90
딴짓을 하게된 계기를 기록하고 대처하는 차원에서 딴짓 원인을 기록하기로 하였다.
사용자는 아래와 같이 3가지 항목중 하나를 드롭박스 옵션에서 골라 선택할 수 있다.
- 내부계기(딴짓을 하게 된 원인이 나로부터 발생한 경우: 피로감, 스트레스 등)
- 외부계기(딴짓을 하게 된 원인이 외부로부터 발생한 경우: 스마트폰 알림, 전화 등)
- 잘못된 계획(딴짓을 하게 된 원인이 잘못된 계획으로부터 발생한 경우)
[배운점]
1. 콜백함수의 선언과 호출
// createNote.js
// 메모 레이아웃 그리기
export function createNote(noteValue, selectValue) {
const notesContainer = document.querySelector('.notesContainer');
// 메모 레이아웃 그리는 내용(...중략)
}
// 생성하기 버튼 이벤트 리스너
const createBtn = document.querySelector('.btn');
createBtn.addEventListener('click', () => {
createNote('', '내부계기'); // 콜백함수 호출
updateStorage();
});
- 콜백함수는 함수내부에서 사용되는 함수이다. 콜백함수 사용 시 어떤 데이터를 받아오는 것인지 헷갈리는 경우가 많았는데, 이번 예제를 통해 그 흐름을 되짚어보고 원리를 파악할 수 있었다.
- createNote 함수는 사용자가 입력한 메모인 noteValue와 드롭박스 옵션인 selectValue를 인자로 받는 함수이다.
- 메모 생성하기 버튼을 클릭하면 'createNote 콜백 함수'를 호출하는 이벤트 리스너를 등록하였다.
- 사용자가 메모와 옵션을 입력하기 전까지는 '빈 문자열'과 '내부계기'옵션이 초기값으로 하여 메모가 생성된다.
- 이어, 사용자가 내용 입력하는 이벤트가 발생하면 그 내용이 스토리지에 저장(updateStorage)된다.
// storage.js
// 파싱한 데이터를 화면에 그리기
function showNotes() {
const savedData = parseSavedData();
console.log('savedData', savedData);
savedData.notes.forEach((note, index) => {
createNote(note, savedData.selects[index]);
});
}
showNotes();
// 로컬스토리지에 저장되는 형식:
// notes: ['하이', '안녕', '메롱'];
// selects: ['외부계기', '내부계기', '잘못된 계획'];
- savedData.notes.forEach((note, index) => { 여기에서 note, index 값을 받는다.
- note는 각각의 요소이다 : '하이', '안녕', '메롱', 각 요소의 index는 0, 1, 2
- showNotes 함수에서 createNote 콜백 함수를 호출하면서 noteValue, selectValue는 각각 note, savedData.selects[index]가 되었다. 드롭박스 옵션의 인덱스는 note의 인덱스와 상응되는 동일한 값을 갖는다.
2. 동적으로 생성되는 dropbox 만드는 방법(option의 속성)
// 동적으로 생성되는 드롭박스 만들기
let dropBox = document.createElement('select'); //select 생성
dropBox.className = 'dropBox';
// option은 드롭다운 버튼 눌렀을 때 열거되는 목록
const options = ['내부계기', '외부계기', '잘못된 계획'];
for (let optionChild of options) {
let option = document.createElement('option');
option.text = optionChild;
dropBox.appendChild(option);
}
dropBox.value = selectValue;
- option 요소는 value 속성과 textContent(또는 text) 속성 모두를 가질 수 있다.
- 그러나 option에 value 속성만 제공하고 text를 제공하지 않으면, 사용자에게 select 드롭다운에서 아무 것도 표시되지 않는다. 따라서 일반적으로는 option에 텍스트 콘텐츠와 value 속성 모두를 제공한다.
- 만약 value와 text가 다르게 설정되어야 하는 경우:
let option = document.createElement('option');
option.value = "internal"; // 저장되는 값
option.textContent = "내부계기";// 화면에서 보여지는 값(option 전체가 다 "내부계기"로 설정됨)
dropBox.appendChild(option);
위와 같이 value는 "internal"로 저장되고, 화면에는 "내부계기"라는 텍스트가 표시된다.
3. input 태그와 div 태그의 속성차이
// [예제1] 저장된 노트 로컬스토리지에서 불러오기
function showNotes() {
notesContainer.innerHTML = localStorage.getItem('allNotes'); //notesContainer는 div
}
showNotes();
function updateStorage() {
localStorage.setItem('allNotes', notesContainer.innerHTML);
}
// [예제2] input 박스 생성하기
let inputBox = document.createElement('input');
inputBox.className = 'inputDiv';
inputBox.value = noteValue; // inputBox는 input
inputBox.placeholder = '딴짓을 기록하세요.';
- input 태그와 div 태그는 다르게 작동하기 때문에 저장하는 데이터의 형태나 가져오는 방식에 차이가 발생한다.
- 1. 데이터 저장 방식의 차이:
- div의 경우 innerHTML 또는 textContent 속성을 사용하여 내용을 가져올 수 있습니다.
- 반면, input의 경우 value 속성을 사용하여 값을 가져와야 한다.
- 2. Event의 차이:
- div의 경우 contenteditable가 설정된 상태에서 내용을 편집할 때 input 이벤트나 keyup 이벤트를 사용할 수 있습니다.
- 반면, input 태그의 경우 값을 변경할 때 input 이벤트나 change 이벤트가 발생한다.
4. 로컬스토리지에 값을 변환하여 저장하기, 불러오기
[ 로컬스토리지에 저장하기 | object →string 변환: JSON.stringfy(object) ]
- 로컬스토리지는 오브젝트를 저장할 수 없기 때문에 문자열로 바꿔 로컬스토리지에 저장해야 한다.
[ 로컬스토리지에서 불러오기 | string → object 변환: JSON.parse(localstorage key) ]
- 로컬스토리지에서 값을 불러올 때는 다시 객체 형태로 변환시켜 사용한다.
- 사용하지 않으면 값은 출력되나 타입이 string 이기 때문에 배열 메소드(forEach 등) 사용 시 오류가 발생한다.
function getSavedData() {
return (
JSON.parse(localStorage.getItem('allNotes')) || {
// allNotes 저장된 값이 있으면 그값을 불러오고, 없으면 [] 빈 값을 반환
notes: [],
selects: [],
}
);
}
5. Array.from ( ) 메소드의 사용
export function updateStorage() {
const notesArray = Array.from(
notesContainer.querySelectorAll('.inputDiv')
).map((input) => input.value);
const selectsArray = Array.from(
notesContainer.querySelectorAll('.dropBox')
).map((select) => select.value);
const savedData = {
notes: notesArray,
selects: selectsArray,
};
saveToLocalStorage(savedData);
}
- Array.from의 필요성:
- Array.from은 문자열과 같은 유사배열객체를 진짜 배열로 바꾸어주는 메소드다. 인자로 유사배열객체와 맵핑함수를 받는다.
- notesContainer.querySelectorAll('.inputDiv'): notesContainer 내부에서 클래스 이름이 'inputDiv' 인 모든 요소들을 NodeList 형태로 선택한다. NodeList는 배열과 유사하지만, 배열의 메서드들을(예: map, filter, reduce 등) 사용할 수 없는 유사배열객체이다.
- 배열의 메서드들 을 사용할 수 없기 때문에, Array.from을 사용하여 NodeList를 실제 배열로 변환한다.
- map((input) => input.value):
- 위에서 변환한 배열의 각 요소 (input)에 대해서 .value 속성을 가져와 새로운 배열을 만든다. 결국, 이 배열에는 inputDiv 클래스를 가진 모든 입력 상자의 값들이 저장된다.
728x90
반응형
'프로젝트 > 딴짓 추적표' 카테고리의 다른 글
[프로젝트] 딴짓추적표 | 트러블슈팅-Cannot read properties of null (0) | 2023.09.20 |
---|---|
[프로젝트] 딴짓추적표 | 3. 검색기능 추가하는 법 (1) | 2023.08.13 |
[프로젝트] 딴짓추적표 | 2. 메모 생성 시간 기록(타임스탬프) 하는 법 (0) | 2023.08.13 |
[프로젝트] 딴짓추적표 | 트러블슈팅-Enter 이벤트 발생에 따른 요소 간 충돌문제 (0) | 2023.08.08 |
[프로젝트] 딴짓추적표 | 1. 레이아웃, 메모 조회 및 갱신하는 법 (0) | 2023.08.08 |