이번에 해결할 문제와 조건이다.
필수 이미지를 검색한 후 결과로 주어진 이미지를 클릭하면 모달이 뜨는데, 모달 영역 밖을 누르거나 / 키보드의 ESC 키를 누르거나 / 모달 우측의 닫기(x) 버튼을 누르면 닫히도록 수정해야 합니다.
현재 그리드의 아이템을 클릭하면 모달의 랜더링 여부를 결정하는 변수 visible이 true가 되어 모달이 innerHTML 형태로 추가되는 구조이다. visiblitiy가 변하는 시점에 생성과 랜더링이 진행되기 때문에 초기에 grid형태로 데이터가 load될 때의 overhead를 줄일 수 있다.
일반적으로 이벤트를 설정하는 방법은 html코드가 있고 js코드에서 DOM으로 접근해 addEventListener를 등록하는 형태이다. 하지만 이 경우에는 컴포넌트가 동적으로 생성되기 때문에, eventListener를 설정해주기 까다롭다.
틀을 먼저 잡아놓고 클릭되는 순간 visibility와 데이터가 전달될 수도 있지 않을까?라는 아이디어를 시작으로 설계했다.
class ImageInfo {
$imageInfo = null;
data = null;
constructor({ $target, data }) {
const $imageInfo = document.createElement("div");
$imageInfo.className = "ImageInfo";
this.$imageInfo = $imageInfo;
this.initialRender();
$target.appendChild(this.$imageInfo);
this.data = data;
// handle close modal
this.$imageInfo.addEventListener('click', () => {
this.$imageInfo.style.display = "none";
})
document.addEventListener('onKeyPress', e => {
if(e.key == 'Escape')
this.$imageInfo.style.display = "none";
})
this.$closeBtn = document.getElementsByClassName('close')[0];
this.$closeBtn.addEventListener('click', ()=> {
this.$imageInfo.style.display = "none";
})
this.render();
}
setState(nextData) {
this.data = nextData;
this.render();
}
initialRender() {
this.$imageInfo.innerHTML = `
<div class="content-wrapper">
<div class="title">
<span class="modal-name"></span>
<div class="close">x</div>
</div>
<div class="modal-image"></div>
<div class="description">
<div>성격: <div class="modal-temperament"></div></div>
<div>태생: <div class="modal-origin"></div></div>
</div>
</div>`;
this.$imageInfo.style.display = "none";
}
render() {
if (this.data.visible) {
const { name, url, temperament, origin } = this.data.image;
let modalImg = document.getElementsByClassName('modal-image')[0];
let modalTemp = document.getElementsByClassName('modal-temperament')[0];
let modalOrigin = document.getElementsByClassName('modal-origin')[0];
modalImg.innerHTML = `<img src="${url}" alt="${name}"/>`
modalTemp.textContent = `${temperament}`;
modalOrigin.textContent = `${origin}`;
this.$imageInfo.style.display = "block";
}
}
}
initial render를 따로 두어, 최초 랜더링시 틀을 잡아놓고
다음 랜더링 그러니까 사진이 클릭되었을 때, 모달에 데이터를 전달하고 시각화 해주는 작업을 했다.
덕분에 모달 내의 요소들과 eventListener의 바인딩이 엇갈리지 않도록 했고, 모달이 띄워질 때마다 HTML을 새로 랜더링할 필요가 없어졌다.
'Frontend > JavaScript' 카테고리의 다른 글
2022-05-16:: [TypeScript]타입을 하고싶어요... (0) | 2022.05.16 |
---|---|
고양이 사진첩 문제를 풀며 느낀점 (0) | 2022.05.14 |
고양이 사진 검색 사이트1 :: 개요, Responsive web (0) | 2022.04.10 |
Sync vs Async (0) | 2021.09.27 |
JEST (0) | 2021.08.31 |