우테코가 비대면으로 이루어지고 있지만 제가 집에만 있다고 노는 건 아닙니다. 할 게 엄청 많습니다.
태그를 적극 활용하려는 노력이 필요합니다.
<input id="search-input-keyword" type="search" placeholder="검색" class="search-input__keyword">
const selectDom = (element, parent = document) => parent.querySelector(element);
@keyframes fadeIn {
from {bottom: 0; opacity: 0;}
to {bottom: 30px; opacity: 1;}
}
@keyframes fadeOut {
from {bottom: 30px; opacity: 1;}
to {bottom: 0; opacity: 0;}
}
.snackbar-container.show {
visibility: visible;
animation: fadeIn 0.6s, fadeOut 0.6s 3.5s;
}
사용 방법 -> MDN 참고했어요.
const form = document.querySelector('form');
const textarea = document.querySelector('textarea');
// 'awesome'이라는 이벤트를 만듭니다.
const eventAwesome = new CustomEvent('awesome', {
bubbles: true, // bubble 옵션을 true로 하고,
detail: { text: () => textarea.value } // detail 안에 전달하고 싶은 데이터를 작성해요.
});
// 'awesome' 이벤트가 발생하면 textarea의 value를 출력합니다.
form.addEventListener('awesome', e => console.log(e.detail.text()));
// form 내부의 textarea에서 input 이벤트가 발생하면,
textarea.addEventListener('input', e => e.target.dispatchEvent(eventAwesome)); // 강제로 dispatchEvent(eventAwesome)을 통해 eventAwesome 이벤트를 발생시킵니다.
// 참고로 이 함수는 스크롤 이벤트 리스너 함수의 콜백함수가 될 겁니다!
onScrollVideoList() {
const { scrollTop, clientHeight, scrollHeight } = this.searchResultVideoList; // 3개의 변수를 가져와서
const searchOnScrollEvent = new CustomEvent('searchOnScroll', {
detail: { scrollTop, clientHeight, scrollHeight }, // serachOnScroll이라는 이벤트가 발생할 때 전달할 값으로 위 3개의 변수를 설정해요.
});
this.searchModal.dispatchEvent(searchOnScrollEvent); //스크롤이벤트 발생시 이 값을 전달해주겠다는 겁니다.
}
의존성을 분리시키고 이벤트에 의존하게 하면서
좀 더 유연하게 처리할 수 있는 장점이 있어요.<ul>
<li class="a"> </li>
<li class="b"> </li>
</ui>
👍 보통 b에서 이벤트 발생했는데, b의 값을 부모인 <ul>
에서 b의 값을 받아 가공하고 a에게 넘겨줄 때 사용한다고 이해했어요. 맞는지는 모르겠고 필요성도 잘 모르겠지만 많은 크루들이 사용하더라구요. 그냥 넘겨요!
addEvent(this.container, {
eventType: EVENT_TYPE.CLICK,
selector: '#remove-video-button',
handler: this.handleClickRemoveButton,
});
👆좋긴한데 코드가 길어지고 굳이? 라는 생각도 좀 드네요.
👇이건 좀 의미가 있어 보이네요!
export const addEvent = (component, eventType, selector, callback) => {
const children = [...component.querySelectorAll(selector)];
const isTarget = (target) => children.includes(target) || target.closest(selector);
component.addEventListener(eventType, (event) => {
if (!isTarget(event.target)) {
return false;
}
return callback(event);
});
};
이걸 싱글톤 패턴이라고 부르네요!
export default class StorageEngine {
static _instance = null;
static get instance() {
if (!StorageEngine._instance) {
StorageEngine._instance = new StorageEngine();
}
return StorageEngine._instance;
}
this.#myVideoList.replaceChildren();
이벤트핸들러는 on/handle + {target} + {eventType}
이런 식으로 네이밍을 합니다.
예를 들면 onXXXClick/Change, handleXXXClick/Change 같은 식으로요!
this.mainView.bindModalOpenButton(this.onModalOpenButtonClick.bind(this));
closest()
를 사용해봅시다.const target = e.target.parentNode.parentNode;
맵을 그려볼까요? 아키텍처 맵은 두 가지로 분리해서 한 번 그려보시면 좋을 것 같아요.
폴더 스트럭쳐: 폴더 스트럭쳐단위로, 서로의 폴더가 어떤걸 참조하고 있는지!
SoC: 관심사 단위로 어떤 것들이 어떻게 분리되고 어떻게 참조하고 있는지!
-> 그려보는 것 또한 공부입니다!