동적으로 생성된 DOM 요소에 액세스하는 방법 - 이벤트 위임/이벤트 버블링/이벤트 전파

프로젝트를 진행하는 동안 동적으로 생성되는 요소에 대한 액세스 권한이 필요했습니다. 사용자가 게시물을 작성하고 수정하고 삭제할 수 있는 소셜 미디어 앱을 구현하고 싶었기 때문입니다. 그러나 나는 문제에 직면했다. 동적으로 생성된 요소는 평소처럼 선택할 수 없기 때문입니다. DOM 요소를 선택하려는 경우 querySelector 또는 getElementById 등을 사용합니다. 그런 다음 상호 작용할 이벤트 리스너를 추가합니다. 그러나 동적으로 생성되기 때문에 처음에는 html에 존재하지 않습니다. JavaScript에 의해 생성되고 나중에 추가됩니다.
따라서 요소가 존재하지 않는다는 오류가 표시됩니다.
또는 null의 addEventListener 오류가 발생합니다.

사용자가 웹사이트에 들어가면 html, css 및 JavaScript와 같은 파일을 다운로드, 읽기, 실행합니다. 그러나 페이지 로드 시 동적으로 생성된 DOM 요소는 아직 없습니다. 브라우저가 API/서버에서 데이터를 수신하거나 사용자가 새 게시물을 작성할 때 생성되고 표시되며(게시물은 데이터가 있을 때만 생성되기 때문에) 초기 페이지 로드 후입니다.

그렇다면 상호 작용할 수 있도록 해당 요소를 선택하려면 어떻게 해야 합니까?
이벤트 위임으로 이 문제를 해결했습니다. 이론만 배웠을 때는 이 작업을 어떻게 해야 할지 확신이 서지 않았습니다.
하지만 내가 가진 문제를 해결하기 위해 실제로 이것을 사용했을 때 그것이 어떻게 작동하는지 더 분명해졌습니다.

이벤트 전파 / 이벤트 위임 / 이벤트 버블링



이벤트 전파란 무엇입니까?
"이벤트 전파는 대상에 도달하기 위해 이벤트가 DOM 트리를 통해 전파 또는 이동하는 방식과 이후에 발생하는 상황을 정의하는 메커니즘입니다."( https://www.tutorialrepublic.com/javascript-tutorial/javascript-event-propagation.php )

이벤트 위임 - 요소 부모의 이벤트 핸들러가 해당 요소에 대한 이벤트를 처리하는 이벤트를 처리하는 특별한 방법입니다. 이것은 이벤트 버블링을 이용하는 방법입니다.
문서 이벤트 또는 문서 요소 이벤트는 DOM 트리를 버블링하고 조상의 이벤트 핸들러를 트리거합니다. 예를 들어 <li> 의 자식 노드인 <ul> 를 클릭하여 이벤트가 발생하면 이 이벤트는 부모 노드인 <ul> 로 전파됩니다. 즉 부모 노드는 자식에게 발생한 이벤트를 감지할 수 있습니다. (또한 자식 노드도 부모에게 발생한 이벤트를 감지할 수 있습니다.)
따라서 이벤트 버블링은 이벤트를 처리하는 다른 방법을 제공합니다.

아래 이미지는 이벤트 전파 방식을 보여줍니다.
사양에서 가져온 테이블 내부의 <td>를 클릭합니다.


출처 -https://javascript.info/bubbling-and-capturing



표준 DOM 이벤트는 이벤트 전파의 3단계를 설명합니다.
캡처 단계 – 이벤트가 요소로 내려갑니다.
대상 단계 – 이벤트가 대상 요소에 도달했습니다.
버블링 단계 – 이벤트가 요소에서 버블링됩니다.

따라서 이벤트는 DOM 트리를 통해 전파됩니다. 즉, 선택한 대상뿐만 아니라 DOM 트리 내에서 대상을 잡을 수 있습니다.
그러나 이벤트 전파를 중지하려면 event.stopPropagation()을 사용하십시오.

이벤트 위임을 사용하여 문제를 해결한 방법.




// 이벤트 위임 - 상위요소에 이벤트를 주면 하위요소까지 다 접근 가능!
const app = document.querySelector("#app");
// 모달 버튼 & 좋아요 클릭 핸들링 
let commentClickedIndex;
let isMyComment = false;
const handleDomClick = (event) => {
  const clickedBtn = event.target;
  if(clickedBtn.classList.contains("setting-logout-btn")){
    openModal(clickedBtn);
  } else if(clickedBtn.classList.contains("post-edit-btn")){
    openModal(clickedBtn);
  } else if(clickedBtn.classList.contains("comment-edit-btn")) {   
    const buttons = document.querySelectorAll(".comment-edit-btn");
    const index = [...buttons].indexOf(clickedBtn)
    commentClickedIndex = index;
    commentAuthorId = commentsListArr[index].author._id;
    // 클릭한 댓글이 내가 쓴 댓글인 경우
    if(commentAuthorId === userId) {
      isMyComment = true;
      openModal(clickedBtn);
    } else {
      isMyComment = false;
      openModal(clickedBtn);
    }
  } else if(clickedBtn.id === "likebtn") {
    applyLike(clickedBtn);
  }

}
app.addEventListener("click", handleDomClick)


위의 코드는 내 프로젝트에 사용된 일부입니다. "앱"내부에 있는 것을 동적으로 생성했기 때문에 내 앱 내부의 다른 요소에 이벤트를 추가할 수 있기를 원했습니다. 그래서 *app인 가장 바깥쪽 요소에 이벤트 리스너를 사용한 다음 각 요소에 대해 특정 작업을 수행하기 위해 해당 요소가 정확히 무엇인지 알기 위해 특정 클래스가 포함되어 있는지 확인했습니다.

** 이벤트 버블링에는 예외가 있습니다.



다음 문서 요소 이벤트는 버블링되지 않습니다: focus, blur, scroll, load/unload 및 mouse event(mouseenter, mouseleave)

좋은 웹페이지 즐겨찾기