Recent Posts
Recent Comments
«   2024/07   »
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30 31
Today
Total
관리 메뉴

DH의 개발 공부로그

[JavaScript] 이벤트 버블링과 캡처링! 본문

JavaScript

[JavaScript] 이벤트 버블링과 캡처링!

DeveloperDH 2023. 4. 5. 23:44
728x90

이벤트 버블링(Bubbling)

이미지 출처 캡틴판교


이벤트 버블링이란 이벤트가 발생했을 때 해당 요소에 할당된 핸들러가 동작하고, 또 상위 요소에 해당 이벤트가 전달이 되어 핸들러가 동작을 하는 현상을 의미합니다. 예시를 보면 훨씬 이해가기가 쉽기 때문에 바로 확인해보겠습니다.

<style>
  div {
    border: 1px solid black;
    padding: 10px;
  }
</style>
<body>
  <div class="div1">
    div1
    <div class="div2">
      div2
      <div class="div3">
        div3
      </div>
    </div>
  </div>
</body>
<script>
  const divs = document.querySelectorAll('div')

  const handleDivClick = (e) => {
    console.log(e.currentTarget.className)
  }

  divs.forEach(div => {
    div.addEventListener('click', handleDivClick)
  });
</script>


이런 구조에서 가장 아래에 위치한 div3을 클릭해서 이벤트가 발생을 하면 상위 요소에게 해당이벤트가 전달이 되면서 핸들러가 작동이 되는 흐름이 바로 이벤트 버블링입니다.
그렇기 때문에 결과는 이렇습니다.

div3를 클릭했을 때 결과

※거의 모든 이벤트는 버블링 됩니다.
여기에서 중요한 키워드는 ‘거의’ 입니다.
focus 이벤트와 같이 버블링 되지 않는 이벤트도 있으며, 몇몇 이벤트를 제외하곤 대부분의 이벤트는 버블링 됩니다.

버블링 막기

가끔 버블링으로 인하여 원하는 작동이 일어나지 않고 방해가 되는 경우가 있을 수 있습니다.
그럴때는 버블링을 막을 수가 있는데, 바로 이벤트 객체의 메서드인 event.stopPropagation()를 사용하면 됩니다.

<body onclick="alert(`버블링은 여기까지 도달하지 못합니다.`)">
  <button onclick="event.stopPropagation()">클릭해 주세요.</button>
</body>

하지만 하나의 요소에 특정 이벤트를 처리하는 핸들러가 여러개인 상황에서는 핸들러 중 하나가 버블링을 중단 시키더라도 나머지 핸들러는 여전히 동작하게 됩니다.
event.stopPropagation()은 위쪽으로 일어나는 버블링은 막아주지만, 다른 핸들러들이 동작하는 건 막지 못하기 때문입니다.
버블링을 멈추고, 요소에 할당된 다른 핸들러의 동작도 막으려면 event.stopImmediatePropagation()을 사용해야 합니다.
event.stopImmediatePropagation() 메서드를 사용하면 요소에 할당된 특정 이벤트를 처리하는 핸들러 모두가 동작하지 않습니다.

꼭 필요한 경우를 제외하곤 버블링을 막는 것을 권장하지 않습니다.

이벤트 캡처링(Capturing)

이벤트 버블링이 있다면 이벤트 캡처링도 있습니다.
이벤트 캡처링은 이벤트 버블링과는 반대의 흐름으로 진행이 되는 이벤트 전파 방식입니다.

이미지 출처 캡틴판교

바로 위의 이미지 처럼 특정이벤트가 발생을 하면 아래에 해당 요소를 찾아서 내려가는 것이 바로 이벤트 캡처링입니다.
그럼 예시로 확인해보겠습니다.

<style>
  div {
    border: 1px solid black;
    padding: 10px;
  }
</style>
<body>
  <div class="div1">
    div1
    <div class="div2">
      div2
      <div class="div3">
        div3
      </div>
    </div>
  </div>
</body>
<script>
  const divs = document.querySelectorAll('div')

  const handleDivClick = (e) => {
    console.log(e.currentTarget.className)
  }

  divs.forEach(div => {
    div.addEventListener('click', handleDivClick, { capture: true // default 값은 false})
  });
</script>

캡처링은 addEventListener에서 옵션으로 capture: true를 설정을 해주면 됩니다. 기본값은 false입니다.
그렇게 해서 버블링때와 같이 div3을 클릭을 해보면 위의 버블링과는 반대의 결과가 나오게 됩니다.

div3를 클릭했을 때 결과

참고

javascript.info - 버블링과 캡처링
캡틴 판교 - 이벤트 버블링, 이벤트 캡처 그리고 이벤트 위임까지

728x90
Comments