Event bubbling and capture MDN 내용 정리

mollog·2021년 3월 7일
0
post-thumbnail
post-custom-banner

원문 링크
여기서 다루는 이벤트 버블링과 캡처링은 자주 접하지 않는 부분이지만 이해하지 못하면 디버깅이 힘든 부분입니다.

이벤트 버블링과 캡처링은 두 개의 이벤트 핸들러가 하나의 요소에서 발생할 때 설명될 수 있는 두 개의 메커니즘입니다.

말로는 모호하니 아래 예시를 보면서 이해해 봅니다.

예시 태그 🔽

<button>Display video</button>

<div class="hidden">
  <video>
    <source src="rabbit320.mp4" type="video/mp4">
  </video>
</div>

태그에 연결된 이벤트들 🔽

btn.onclick = function() {
  videoBox.setAttribute('class', 'showing');
}

videoBox.onclick = function() {
  videoBox.setAttribute('class', 'hidden');
};

video.onclick = function() {
  video.play();
};

버튼을 누르면 비디오가 보이는 이벤트
비디오를 누르면 비디오가 재생되는 이벤트
비디오 박스를 누르면 비디오가 사라지는 이벤트가 걸려있습니다.

그런데 버튼을 눌러서 비디오가 보인 후
비디오 박스를 누르면 비디오가 사라진 채로 비디오가 실행이 됩니다.

이벤트 캡처링 영역

브라우저는 요소의 가장 바깥 태그인 html에 이벤트 캡처를 시키기 위해 등록된 onclick 이벤트 핸들러를 찾아 들어갑니다. html > div.hidden > video

이벤트 버블링 영역

브라우저는 선택된 요소의 onclick 이벤트 핸들러를 부모에게 전달해서 부모의 이벤트 핸들러를 호출하고 계속 이런 식으로 부모의 부모 이벤트를 호출하다 html까지 올라갑니다.

=> 브라우저에서는 기본적으로 모든 이벤트 핸들러가 이렇게 이벤트 버블링 단계에 등록됩니다.
(타고 타고 타고 올라가기)

그렇기 때문에 비디오를 눌렀을 때 비디오만 실행되는 게 아니라 비디오박스 이벤트까지 실행되어서 비디오가 사라지게 된 것입니다.

stopPropagation()으로 문제 해결하기?

이렇게 이벤트들이 계속 버블업되면 예상치 못한 이벤트들도 발생하기에 굉장히 성가십니다.
이벤트 객체는 기본적으로 stopPropagation()이라는 이벤트를 호출할 수 있는데 이것을 호출하면, 호출된 처음 이벤트만 실행이 되고 그 위로는 더이상 이벤트가 버블업되지 않습니다.

video.onclick = function(e) {
  e.stopPropagation();
  video.play();
};

하지만 stopPropagation()을 사용하면 해당 요소를 클릭했을 때 다른 이벤트가 발생되기를 원하는 로직에서 문제가 생길 수 있습니다.
그렇기 때문에 위 함수를 호출하기보다는 실제로 이벤트가 발생한 타겟 === 현재 타겟이 일치하는지 불일치하는지를 구분하는 로직을 사용하는 것이 더 효율적입니다. 👍

video.onclick = function(e) {
  if (e.target !== e.currentTarget) {
    return;
  }
  video.play();
};

** 왜 브라우저가 버블링 캡처링을 신경쓰게 됐을까?
아주 오래전 태초의 구식 브라우저는 이벤트 캡처만 사용했고 인터넷 익스플로러는 이벤트 버블링만 사용했습니다. 그리고 W3C가 브라우저 행동을 표준화하기 위해 합의점을 가질 때 이 두 개의 이벤트 매커니즘을 같이 포함하는 시스템으로 결정되었다고 합니다.

post-custom-banner

0개의 댓글