lang="ko"의 의미
<!DOCTYPE html>
<html lang="ko">
</html>
타입을 주석으로 다는 방법 JsDoc
https://poiemaweb.com/jsdoc-type-hint
CSS :root
https://developer.mozilla.org/en-US/docs/Web/CSS/:root
:root {
--purple: #6b4eff;
--purple-light: #e7e7ff;
--purple-dark: #543cce;
--border: #f2f4f5;
--background: #f1f4f8;
--primary: #090a0a;
--secondary: #72777a;
--todo-size: 380px;
}
css 변수를 사용하는 방법은 다음과 같다.
.global-header {
...
max-width: var(--todo-size);
...
}
before 가상 선택자를 사용한 이모지 추가
<hgroup>
<h2 class="todo-name">Todo name</h2>
<small class="todo-count">2/2</small>
</hgroup>
.todo-header hgroup .todo-name::before {
content: "📄 ";
}
flex gap
flex gap을 사용하면 다음처럼 padding을 준 효과를 낼 수 있다.
<label class="form-check-group">
<input class="form-check" type="checkbox" checked />
<span>isCompleted 값이 true</span>
</label>
.form-check-group {
display: flex;
align-items: center;
flex: 1;
gap: 12px;
height: 65px;
}
HTML 파일
script를 모듈로 쪼개서 가져왔다.
<!DOCTYPE html>
<html lang="ko">
<body>
...
<script src="./TodoList.js"></script>
<script src="./index.js"></script>
</body>
</html>
input && eventListner
EventListner('keydown')을 사용했다.
$addInput.addEventListener('keydown', (e) => {
if (e.code !== 'Enter' || e.isComposing) return; // 엔터가 아니면 eventListener 빠져나가기
e.preventDefault();
const input = e.target;
todoList.addTodo(input.value);
input.value = '';
});
키를 입력 받을 수 있는 이벤트 리스너는 대표적으로 두가지가 있다.
- onKeyDown - 한/영, Shit, Backspace 인식 가능
- onKeyPress - 한/영, Shit, Backspace 인식 불가능
투두리스트에서는 한/영이 입력가능해야했기 때문에 onKeyDown을 사용해야한다.
e.code
e.code 는 현재 입력한 키가 무엇인지 스트링 형태로 반환해준다.
e.isComposing
처음에 이 코드를 보면서 '오케이 Enter 키가 입력되지 않으면 해당 이벤트를 빠져나가게끔 하려는 구나' 그런데 e.isComposing은 왜 넣은거지? 라고 생각했다.
if (e.code !== 'Enter' || e.isComposing) return;
그 이유를 설명을 하면, 영어를 입력할 때에는 e.isComposing = false 이고 Enter도 한번만 입력된다.
그런데 한글로 입력을하면 e.isComposing = true 이고 Enter 가 두번나온다. 첫번째 Enter는 e.isComposing이 true
두번째 Enter는 e.isComposing = false 인 상태로 말이다.
이렇게 엔터가 두번입력되기때문에 오류가 생긴다.
다음처럼 말이다.
내가 원하지 않은 값이 투두리스트에 들어가게 되어버렸다.
그렇기 때문에 한글일 경우 e.isComposing = true 인 Enter를 걸러 주어 한번만 엔터가 입력되게 하는 로직이다.
e.preventDefault()
해당 코드가 들어가 있는 이유는 새로고침을 막기 위함이다.
e.preventDefault();
addTodo
스프레드 연산자를 사용하고 뒤에 새로들어온 text 값을 isCompleted 프로퍼티와 함께 객체로 이어서 newData를 만든모습이다. es6 에 익숙해지도록 코드를 많이보자.
this.addTodo = (newText) => {
console.log(todoList); // TodoList {data: Array(2), $target: ul.todo-list, validate: ƒ, render: ƒ, setState: ƒ, …}
const newData = [...todoList.data, { text: newText, isCompleted: false }];
todoList.setState(newData);
};
HTML 데이터셋 (Dataset, data -* )
https://blogpack.tistory.com/680
다음과 같이 data- 로 시작하는 속성에 접근할 수 있는 방법이 있는데 코드는 다음과 같다.
const targetIndex = todoItem?.dataset.index;
주의해야할점은 string이 할당된다는 것이다. 후에 number 인 primitive와 비교할때 조심해야한다.
완료한 투두리스트를 삭선으로 표시하는 코드는 다음과 같다.
다음 스프레드 연산자는 객체를 편다는 느낌으로 받아들이면 되고 펴진 객체중에서 프로퍼티의 key값이 isCompleted인 값을 변경하는 코드이다.
공부하다가 든 생각인데 map 과 forEach 의 차이는 forEach는 순전히 iterate를 위한 함수이고 , map은 배열을 반환한다는 것에서 다르다.
this.toggleTodo = (index) => {
const newData = this.data.map((todo, i) =>
i === parseInt(index) ? { ...todo, isCompleted: !todo.isCompleted } : todo
);
this.setState(newData);
};
deleteTodo
this.deleteTodo = (index) => {
const newData = this.data.filter((todo, i) => i !== parseInt(index));
this.setState(newData);
};
closeset
target.parentNode
위 코드도 상위 엘리먼트가 하나라면 문제가 되지 않았겠지만, 만약에 상위 3계층위의 엘리먼트에 접근을 해야했다면 ?
아래 코드를 보자 딱보기에도 이상한 것 같다.
target.parentNode.parentNode.parentNode
위와 같은 문제를 해결하기 위해서 closest 를 사용했다.
$todo.addEventListener('click', (e) => {
const target = e.target;
if (target.classList.contains('form-check')) {
const todoItem = target.closest('.todo-item');
console.log(todoItem);
const targetIndex = todoItem?.dataset.index;
todoItem && todoList.toggleTodo(targetIndex);
}
'공부기록 > 웹 개발' 카테고리의 다른 글
[Material-UI] sx props style (0) | 2022.07.21 |
---|---|
어느 망한 하루의 시작 (0) | 2022.07.21 |
CSS 가상 셀렉터(Pseudo Selector) :active, :hover, :focus (0) | 2022.07.19 |
CSS 초기화 하는 방법 (0) | 2022.07.19 |
[CSS Grid] 영역 이름 사용하기 grid-template-areas (0) | 2022.07.17 |