[JavaScript] 이벤트 버블링, 이벤트 캡쳐, 이벤트 위임

KimYoungWoong·2022년 7월 24일
0
post-thumbnail

📢 들어가기 전에...


Udemy에서 메이커준님의 강의를 수강하던 중, 이벤트 위임이라는 코딩 패턴을 접하고 사용해보았습니다. 굉장히 유용하고 편한 방식인 것 같고 신기해서 공부를 하기 위하여 정보를 찾고 글로 정리해보았습니다.


📄 이벤트 버블링 - Event Bubbing


이벤트 버블링이란 어떤 화면 요소에 이벤트가 발생하면 이 요소에 할당된 핸들러가 동작하고, 그 다음 부모 요소의 핸들러가 동작합니다. 이 동작은 가장 상단의 조상 요소를 만날 때까지 반복되며, 각각 할당된 핸들러가 동작합니다.

예제 코드를 보시겠습니다.

  <body>
    <div class="A">
      A
      <div class="B">
        B
        <div class="C">C</div>
      </div>
    </div>
  </body>
const div = document.querySelectorAll("div");
div.forEach((v) =>
  v.addEventListener("click", (e) => {
    console.log(e.currentTarget.className);
  })
);

이 코드는 각 div를 클릭하면 클릭한 div의 className이 출력되는 코드입니다.
<div class="C">C</div>를 클릭하면 다음과 같은 동작이 발생됩니다.
1. C div에 할당된 클릭 이벤트 리스너가 동작합니다.
2. C div의 바깥인 B div에 할당된 클릭 이벤트 리스너가 동작합니다.
3. B div의 바깥인 A div에 할당된 클릭 이벤트 리스너가 동작합니다.
4. document 객체를 만날 때까지 요소에 할당된 핸들러가 동작합니다.

결과는 다음과 같이 출력됩니다.

거의 모든 이벤트는 버블링되지만, 버블링 되지 않는 이벤트도 존재합니다.

📄 이벤트 캡처링 - Event Capturing


이벤트 캡처링은 이벤트 버블링과는 반대로 window에서부터 이벤트가 발생한 요소까지 반복하며 동작하는 것입니다.
예제 코드입니다.

  <body>
    <div class="A">
      A
      <div class="B">
        B
        <div class="C">C</div>
      </div>
    </div>
  </body>
const div = document.querySelectorAll("div");
div.forEach((v) =>
  v.addEventListener("click", (e) => {
    console.log(e.currentTarget.className);
  }, true)
);

결과는

버블링과 다른 점은 이벤트 리스너의 3번째 인자로 true를 줬다는 것입니다.

📄 event.stopPropagation()


버블링과 캡처링을 막으려면 stopPropagation()란 웹 API를 사용하면 됩니다.
stopPropagation()은 동작할 이벤트가 전파되는 것을 막는 기능을 합니다.


📄 이벤트 위임 - Event Delegation


이벤트 위임은 하위 요소들에게 각각 이벤트 리스너를 붙이지 않고 상위 요소에 붙여서 하위 요소들의 이벤트를 제어하는 것이라고 할 수 있습니다.
하위 요소가 적다면 상관 없을 수 있지만, 엄청 많다면 하나 하나에 이벤트 리스너를 붙이기는 시간 소모도 많고 귀찮기 때문에, 상위 요소 하나에 이벤트 리스너를 붙여 편하게 관리할 수 있는 것입니다.

예제 코드는 강의를 들으며 만든 코드입니다.

<nav class="menu-button-list">
  <button data-category-name="espresso" class="cafe-category-name">☕ 에스프레소</button>
  <button data-category-name="frappuccino" class="cafe-category-name">🥤 프라푸치노</button>
  <button data-category-name="blended" class="cafe-category-name">🍹 블렌디드</button>
  <button data-category-name="teavana" class="cafe-category-name">🍵 티바나</button>
  <button data-category-name="desert" class="cafe-category-name">🍰 디저트</button>
</nav>
$nav_menuBtn.addEventListener("click", (e) => {
      const btn = e.target.closest("button");
      if (btn) {
        const categoryName = btn.dataset.categoryName;
        this.currentCategory = categoryName;
        $menu_title.textContent = `${e.target.innerText} 메뉴 관리`;
        render();
      }
    });

이벤트 위임을 사용하지 않는다면 버튼 각각에 이벤트 리스너를 달아야 하므로 가독성도 좋지 않고 시간 소모도 많을 것입니다.
하지만 이벤트 위임을 사용한다면 상위 요소인 nav 태그에 이벤트 리스너를 달아서 하위 요소인 버튼을 눌렀을 때, 누른 버튼을 찾아 이벤트를 동작할 수 있습니다.

이벤트 위임의 장점을 정리해보면,
1. 동적인 요소에 대한 이벤트 처리가 쉽습니다.
2. 상위 요소에서 이벤트 리스너를 관리하기 때문에, 하위 요소는 추가, 삭제가 편합니다.
3. 가독성이 좋습니다.


참고
왜 이벤트 위임을 해야 하는가
이벤트 버블링, 이벤트 캡처 그리고 이벤트 위임까지

profile
블로그 이전했습니다!! https://highero.tistory.com

0개의 댓글