JavaScript - 이벤트 버블링과 이벤트 캡처링

김서영·2024년 2월 11일
0

이벤트 버블링(Event Bubbling)


이벤트가 발생한 요소부터 점점 부모 요소를 거슬러 올라가서 window까지 이벤트를 전파하는 것

예시)

<html>
  <body>
    <!-- 분홍색 -->
    <div class="pink" onClick="alert(this.className)">
      <!-- 보라색 -->
      <div class="purple" onClick="alert(this.className)">
        <!-- 파란색 -->
        <div class="blue" onClick="alert(this.className)">
          blue
        </div>
      </div>    
    </div>
  </body>
</html>
  1. blue 영역을 클릭하면 onClick 핸들러 동작
  2. 부모 요소인 purple의 onClick 핸들러 동작
  3. 부모 요소인 pink의 onClick 핸들러 동작

거의 모든 이벤트는 버블링이 된다!!

그러면 무조건 버블링이 실행되야 하는지???

버블링 강제 중단 방법

event.stopPropagation()을 활용하면 된다!!

예시)

<html>
  <body>
    <!-- 분홍색 -->
    <div class="pink" onClick="alert(this.className)">
      <!-- 보라색 -->
      <div class="purple" onClick="alert(this.className); event.stopPropagation()">
        <!-- 파란색 -->
        <div class="blue" onClick="alert(this.className)">
          blue
        </div>
      </div>    
    </div>
  </body>
</html>

이렇게 작성하면 파랑색, 보라색 alert만 뜨고 분홍색 alert는 뜨지 않는다!!

하지만 하나의 요소에서 다양한 이벤트 핸들러가 존재할 경우, event.stopPropagation()을 활용하면 이벤트들 중 하나만 버블링을 멈추고 나머지 이벤트들은 동작하게 된다.

하나의 요소에 할당된 모든 이벤트 동작을 막기 위해서는 event.stopImmediatePropagation()을 활용해야 한다!!

버블링은 유용한 기능이기 때문에 버블링을 꼭 멈춰야 하는 상황이 아니라면 버블링을 막지 않는것이 좋다!!

이벤트 캡처링(Event Capturing)


window부터 이벤트가 발생한 요소까지 이벤트를 전파하는 것

캡처링을 활용하려면 addEventListener의 capture 옵션을 true로 설정해야 한다!

elem.addEventListener(..., {capture: true})
// {capture: true} 대신 간단하게 true만 작성해도 됨!
elem.addEventListener(..., true)

예시)

<html>
  <body>
	<!-- 분홍색 -->
    <div class="pink">
      <!-- 보라색 -->
      <div class="purple">
        <!-- 파란색 -->
        <div class="blue">
          blue
        </div>
      </div>    
    </div>
  </body>
  <script>
    for(let elem of document.querySelectorAll('*')) {
  	elem.addEventListener("click", e => alert(`[캡쳐링] tag: ${elem.tagName}, class: ${elem.className}`), true);
  	elem.addEventListener("click", e => alert(`[버블링] tag: ${elem.tagName}, class: ${elem.className}`));
  }
  </script>
</html>

이렇게 작성하게 되면, 가장 상단 요소에서부터 이벤트 전파가 시작되었다가, 클릭한 부분까지 오면 다시 버블링이 시작된다!!
1. html(캡처링)
2. body(캡처링)
3. pink(캡처링)
4. purple(캡처링)
5. blue(캡처링)
6. blue(버블링)
7. purple(버블링)
8. pink(버블링)
9. body(버블링)
10. html(버블링)

이벤트 위임


이벤트 버블링을 활용하여 상위 요소에만 이벤트 리스너를 등록하는 기법

사용자의 액션에 의해 이벤트 발생 시 이벤트 버블링에 의해 document 레벨까지 버블링 되어 올라가는데 이 작동 방식을 이용해 자식 엘리먼트의 각각에 모든 이벤트를 주지 않고, 부모에게만 이벤트를 위임하는 방법
=> 여러 개의 이벤트 리스너를 등록하지 않고 상위 요소에 하나의 이벤트 리스너만 등록하는 것

예시)

<html>
  <body>
    <!-- 분홍색 -->
    <div class="pink" id="container">
      <!-- 보라색 -->
      <div class="purple">
        <!-- 파란색 -->
        <div class="blue">
          blue
        </div>
      </div>    
    </div>
    <script>
      document.getElementById("container").addEventListener("click", function(event) {
        if (event.target.className) {
          alert(event.target.className);
        }
      });
    </script>
  </body>
</html>

상위 요소에 이벤트 리스너를 추가하고, 하위 요소에서 실제 이벤트가 발생했을때 상위 요소에서 이를 처리하는 것!

  1. container요소에 클릭 이벤트를 추가(클릭된 요소의 클래스 이름을 알리는 역할)
  2. 클릭된 요소의 클래스 이름을 활용해 alert 이벤트 실행
  3. 하위요소에 클릭 이벤트가 발생해도, 상위 요소에서 한번에 처리

이벤트 위임의 장점

  • 메모리 사용량 감소
  • 코드를 더 간결하게 작성
profile
개발과 지식의 성장을 즐기는 개발자

0개의 댓글

관련 채용 정보