📖 오늘 배운 것
컴포넌트 방식으로 생각하기
- Simple Todo List 만들기
컴포넌트 방식으로 만드는 것은 어렵다
- UI를 선언적으로 표현하기 위해 표현하는 부분들을 추상화 가능하다.
- Header, TodoForm, TodoList, 그리고 이 세가지 컴포넌트들을 관리할 app
- 각자를 하나의 단위로 보고 나눈다.
- 이 모든 것을 하나로 합칠 app이 필요함
- 이렇게 추상화를 진행해 놓으면 수정 단계에서 해당 화면에서 입력받는 것만 고치면 된다.
1. TodoList
- 파라미터: target(어느 화면? 에 표시될 것인지 , append 될 것인지), state (todoLIst에 표현할 데이터)
- 받은 파라미터들로 데이터를 계산하여 화면에 출력
function TodoList({$target, initialState}) {
const $todoList = document.createElement('div');
$target.appendChild($todoList);
this.state = initialState;
this.setState = (nextState) => {
this.state = nextState;
this.render(); // state가 바뀌고 화면을 바꿔주어야함
}
this.render = () => {
$todoList.innerHTML = `
<ul>
${this.state.map(({text}) => `<li>${text}</li>`).join('')}
</ul>
`
}
this.render(); // 맨 처음 rendering때 필요
}
2. TodoForm
- 파라미터: target(위와 동일), onSubmit(input의 입력결과를 app으로 빼서 TodoList에 사용하여 직접적인 의존성을 가지지 않게 하기 위함)
- 입력받은 밸류를 onSubmit 함수를 통해 app으로 뺀 후 TodoList에 전해줌
- 입력받은 밸류를 localStorage에 저장
function TodoForm({$target, onSubmut}) {
const $form = document.createElement('form');
$target.appendChild($form);
let isInit = false; // 목적성?
this.render = () => {
$form.innerHTML = `
<input type="text" name="todo"/>
<button>add</button>
`
if(!isInit) {
$form.addEventListener('submit', e => {
e.preventDefault();
const input = $form.querySelector('input[name=todo]');
// 입력 후 밸류 초기화를 위함
const value = input.value;
input.value = '';
// value값이 빈 값일 경우 추가 안하기 위함
if(value.length > 1) {
onSubmit(value);
}
})
isInit = true;
}
}
this.render();
}
3. Header
- 파라미터: target(위와 동일), text (없어도 됨 솔직히 걍 이름 정해주기 위하)
function Header({$target, text}) {
const $header = documenrt.createElement('h1');
$target.appendChild($header);
this.render = () => {
$header.textContent = text;
}
this.render();
}
4. App
- 파라미터: target (main에서 선언해서 뿌려줌), initialState(localStorage에서 받아온 todoList)
function App({$target, initialState}) {
new Header({$target, text: 'Simple TodoList'});
new TodoForm({$target,
onSubmit: (text) => {
const nextState = [...todoList.state, {text}];
todoList.setState(nextState);
storage.setItem('todos', nextState);
})
const todoList = new TodoList({$target, initialState})
}
5. storage
- 파라미터: window.localStorage (localStorage 를 사용하기 위함)
- 즉시실행 함수(전역 오염을 최소화하기 위함)로 구현함
- json 형태가 아닌 데이터가 올 수도 있으니 try/catch 문을 활용해 storage.js 에서 관리하기 위함
const storage = (function(storage) {
const setItem = (key, value) => {
try {
storage.setItem(key,JSON.stringify(value));
}catch (e) {
console.log(e.message);
}
}
const getItem = (key, defaultValue) => {
try {
const storageValue = storage.getItem(key);
if(storageValue) {
return JSON.parse(storageValue);
}
return defaultValue;
}catch (e) {
console.log(e.message);
return defaultValue;
}
}
const removeItem = (key) => {
storage.removeItem(key);
}
return {
setItem,
getItem,
removeItem
}
})(window.localStorage)
이렇게 Simple TodoList 구현이 완료 되었다.
오늘 꼭 기억해야 할 것을 다시 적어보자
- 컴포넌트화를 하는 이유는? 추상화를 통해 코드 재사용성이나, 코드를 고칠 경우 해당 컴포넌트만 고치면 되는등 장점이 많다.
- 컴포넌트를 나누는 기준? 서로 의존성이 없는 경우에 가장 좋음. 화면을 기준으로 나눈 다음 모든 컴포넌트들을 App 컴포넌트에 넣어주어서 관리해도 됨
- 의존성을 최대한 없게 코드를 구성하자.
=> 컴포넌트 생성 파라미터에 다른 컴포넌트를 넣지말고, 콜백 함수를 통해 해당 데이터를 뽑아서 setState와 같은 함수로 App 컴포넌트에서 데이터들을 뿌려준다. - form 에는 action이라는 속성이 있는데 없는 경우 디폴트 값으로 자기 자신의 url을 넣어주어 submit하는 경우 계속해서 새로고침이 되므로 e.prevenDefault()로 디폴트 작업들을 막아주어야 함
'데브코스' 카테고리의 다른 글
[VanillaJS] TodoList에 Drag & Drop 이벤트 적용시키기 (feat. taskQueue) (0) | 2022.11.24 |
---|---|
VanillaJS를 통한 자바스크립트 정리 2 (0) | 2022.11.02 |
프로그래머스 데브코스 2주차 회고록 😝 (0) | 2022.10.31 |