Q 어떤 문제가 있었는지
미니 프로젝트의 방명록 페이지 구현에서 수정 버튼과 삭제 버튼의 클릭 이벤트가 버튼을 두 번 클릭했을 때 작동하는 문제가 있었다.
수정 버튼과 삭제 버튼을 구현한 코드는 다음과 같다.
document.addEventListener("click", async (e) => {
if (e.target.className === "delete") {
const deleteItems = document.querySelectorAll(".delete");
deleteItems.forEach((item) => {
item.addEventListener("click", async function () {
// 삭제에 대한 처리
});
});
}
if (e.target.className === "insert") {
const insertItems = document.querySelectorAll(".insert");
insertItems.forEach((item) => {
item.addEventListener("click", function () {
// className이 "insert"인 여러 요소(태그) 중 "click" 이벤트가 발생한 요소에 대한 처리
});
});
}
if (e.target.className === "update") {
// 수정된 방명록의 텍스트를 인식해서 firebase.js로 넘기는 코드
}
});
코드를 이렇게 작성한 이유는 이전 ITL에 남긴 기록과 같이 데이터를 불러오면서 동적으로 태그를 삽입하는 방식이고 동일한 className을 사용하기 때문에 단일 요소의 이벤트 처리 방법인 document.querySelector().addEventListener()로 이벤트를 처리를 할 수 없었고 위와 같이 querySelectorAll()을 사용하여 className이 'delete'인 요소들을 가져와서 그 중 'click' 이벤트가 발생한 요소에 대한 처리를 해야 했다.
Q 내가 시도해본 것들
- log로 클릭 이벤트가 정상적으로 동작하는지 확인(log는 두 번 출력되지만 이벤트는 두 번째 클릭에서 발생함)
- document.addEventListener에서 window.addEventListener로 변경해봤지만 동일
- window.addEventListener("DOMContentLoaded", listener)에 delete에 대한 addEventListener 추가(동작 X)
Q 어떻게 해결했는지
window.addEventListener("DOMContentLoaded", listener) 안에서 DOM load 후 내부에서 추가 이벤트 리스너 구현없이 document.querySelectorAll().forEach()를 추가했다.
window.addEventListener("DOMContentLoaded", async () => {
/*
생략된 코드
- 쿠키를 확인하고 사용자 아이디가 없으면 로그인 페이지로 이동 코드
- DOM load 후 Cloud Firestore에서 데이터를 받아오는 코드
*/
const deleteItems = document.querySelectorAll(".delete");
deleteItems.forEach((item) => {
item.addEventListener("click", async function () {
// 로그인된 사용자와 작성자가 일치하는지 확인 후 삭제하는 코드
});
});
const insertItems = document.querySelectorAll(".insert");
insertItems.forEach((item) => {
item.addEventListener("click", function () {
// 로그인된 사용자와 작성자가 일치하는지 확인 후 수정하는 코드
});
});
});
document.addEventListener("click", async (e) => {
if (e.target.className === "update") {
// 수정된 방명록의 텍스트를 인식해서 firebase.js로 넘기는 코드
}
});
삭제 로직에 이벤트 타겟의 this를 사용하여 코드를 작성했을 때, this를 console에 출력하면 다음과 같이 출력된다.
Q 뭘 새롭게 알았는지
- 같은 className을 갖고 있는 요소들에 이벤트를 적용할 때 document.querySelectorAll().forEach()를 사용한다.
- forEach()내 forEach((item) => { item.addEventListener("click", async function () { ... }와 같이 요소들에 이벤트가 적용되므로 상위에 이벤트 리스너를 더 추가할 필요가 없다.
- DOM load 후 이벤트 처리를 위해서는 window.addEventListener("DOMContentLoaded", listener)를 사용한다.
참고 링크
'JavaScript' 카테고리의 다른 글
[JavaScript] fetch (0) | 2024.06.03 |
---|---|
[JavaScript] URL에서 쿼리 문자열 추출 방법(URLSearchParams) (1) | 2024.04.18 |
DOM Node에 #text가 추가되는 이유 (0) | 2024.04.17 |
JavaScript의 Module (0) | 2024.04.16 |