classList의 toggle 기능을 활용하면 쉽게 모달을 켜고 끌 수 있다.
const backDropToggle = () => {
backDrop.classList.toggle("visible");
};
toggle은 해당 CSS 클래스가 존재하면 CSS 클래스를 삭제하고, 존재하지 않으면 추가하는 방식이다. 따라서 만약 display : block 등의 내용을 담고 있는 CSS 클래스 visible이 존재한다면, 위와 같이 활용할 수 있다. classList는 DOM이 가지고 있는 모든 CSS 클래스를 반환한다.
게시판 기능을 구현하고자 할 때, 내가 input창에 기입한 정보를 토대로 그것이 리스트의 구성요소가 되어 추가되어야 한다.
DOM 객체를 만들고 추가하는 순서는 다음과 같다(리스트를 추가하는 상황 가정)
1. createElement를 통해 DOM 객체를 만든다
2. className을 지정해 스타일을 입힌다.(CSS 클래스가 만들어져있다는 가정 하에)
3. innerHTML을 통해 아까 만든 DOM객체에 내용을 추가한다.
4. 만든 객체를 append를 통해 리스트를 추가한다.
const renderNewMovie = (imageUrl, title, rating, id) => {
const newMovieElement = document.createElement("li");
newMovieElement.className = "movie-element";
newMovieElement.innerHTML = `
<div class = "movie-element__image">
<img src ="${imageUrl}" alt=${title}>
</div>
<div class="movie-element__info">
<h2>${title}</h2>
<p>${rating}/5 stars</p>
</div>
`;
const listRoot = document.getElementById("movie-list");
newMovieElement.addEventListener("click", deleteModal.bind(null, id));
//바로 위 라인 코드는 새로 만든 객체에 이벤트리스너를 달아주는 것이다.
listRoot.append(newMovieElement);
console.log(listRoot);
};
만약 반복적으로 실행되는 함수안에 이벤트 리스너를 지정하는 코드가 작성되어있다면, 함수가 실행될 때 마다 이벤트 리스너가 생성되어, 이벤트가 발생하였을 때 생성된 이벤트 리스너만큼 이벤트 리스너에 연결딘 함수가 실행될 것이다. 이러한 상황은 끔찍하기 때문에 피해줘야 한다.
이러한 경우는 간단하게 removeEventListner를 이용하면 된다. 주의할 점은 이것을 먼저 호출한 뒤에 이벤트리스너를 등록해야 한다. 왜냐하면 remove가 뒤에 호출되면 앞전에 존재하는 모든 이벤트 리스너가 삭제되기 때문이다. 하나를 남겨놓기 위해 다음과 같이 코드를 작성한다.
cancleButton.removeEventListener("click", closeConfirmModal);
cancleButton.addEventListener("click", closeConfirmModal);
이러한 경우는 복잡해진다. 왜냐하면 removeEventListner가 먹지를 않기 때문이다.
// 1. DOM에서 객체를 가져옴
let approveButton = cancleButton.nextElementSibling;
// 2. 가져온 객체를 복제하여 가져온 객체를 대체함
// 이 과정은 새로운 객체를 만들어서 대체하는 것이므로 이벤트리스너가 없고,
// 변수 approveButton의 참조도 끊긴다.
approveButton.replaceWith(approveButton.cloneNode(true));
// 3. 따라서 새로 만들어서 대체한 객체를 다시 참조한다.
approveButton = cancleButton.nextElementSibling;
// 4. 이벤트 리스너를 추가한다.
approveButton.addEventListener(
"click",
approveMovieDeleteHandler.bind(null, id)
);
정말 쉽게 말하면 초기화 한다음에 이벤트 리스너를 추가하는 것이다. 위의 상황이랑 원리는 동일하다는 뜻이다.
const modalAddButtonHandler = () => {
const titleValue = userInputs[0].value;
const imageUrlValue = userInputs[1].value;
const ratingValue = userInputs[2].value;
if (
titleValue.trim() === "" ||
imageUrlValue.trim() === "" ||
ratingValue.trim() === "" ||
ratingValue < 1
) {
alert("올바르게 입력하시오");
} else {
//객체를 만듦
const movie = {
id: Math.random().toString(),
title: titleValue,
imageUrl: imageUrlValue,
rating: ratingValue,
};
//만든 객체를 배열에 저장함
movies.push(movie);
updateBanner();
closeModal();
renderNewMovie(imageUrlValue, titleValue, ratingValue, movie.id);
console.log(movies);
}
};