이벤트 버블링과 캡처링

Mintaek·2023년 10월 16일

JavaScript

목록 보기
2/8
post-thumbnail

이벤트 버블링과 캡처링

먼저 이벤트 등록에 대해 알아보자. 이벤트 등록은 간단히 말해서 웹 애플리케이션에서 사용자의 입력을 받기 위해 필요한 기능을 말한다. 아래는 간단한 버튼 이벤트 등록 코드이다.

<button>add item</button>
var button = document.querySelector('button');
button.addEventListener('click', addItem);

function addItem(event) {
	console.log(event);
}
  • 위 코드는 add item 버튼을 만들어 클릭하면 addItem 함수를 실행시키는 코드이다
  • addEventListner() 웹 API는 사용자의 입력에 따라 추가 동작을 구현할 수 있는 방법

브라우저의 이벤트 감지 방식 2가지

이벤트 버블링 (Event Bubbling)

특정 화면 요소에서 이벤트가 발생했을 때 해당 이벤트가 더 상위의 화면 요소들로 전달되어 가는 특성.

버블링 예제

<style>
  body * {
    margin: 10px;
    border: 1px solid blue;
  }
</style>

<form onclick="alert('form')">FORM
  <div onclick="alert('div')">DIV
    <p onclick="alert('p')">P</p>
  </div>
</form>
  • 가장 안쪽의<p>를 클릭하면 순서대로 다음과 같은 일이 벌어진다.
  1. <p>에 할당된 onclick 핸들러가 동작.
  2. 바깥의 <div>에 할당된 핸들러가 동작.
  3. 그 바깥의 <form>에 할당된 핸들러가 동작.
  4. document 객체를 만날 때까지, 각 요소에 할당된 onclick 핸들러가 동작.

event.target

부모 요소의 핸들러는 이벤트가 정확히 어디서 발생했는지 등에 대한 자세한 정보를 얻을 수 있다.

  • evenet.target 과 this(=event.currentTarget)의 차이
  1. event.target은 실제 이벤트가 시작된 ‘타깃’ 요소. 버블링이 진행되어도 변하지 않는다.
  2. this는 ‘현재’ 요소로, 현재 실행 중인 핸들러가 할당된 요소를 참조

위 예제에서의 event.target 과 this

  1. this(event.currentTarget) – <form> 요소에 있는 핸들러가 동작했기 때문에 <form> 요소를 가리킨다.

  2. event.target - 폼 안에 실제로 클릭한 요소

버블링 막기

몇몇 이벤트는 window 객체까지 거슬러 올라가기도 하는데, 이 때에도 모든 핸들러가 호출된다. 그런데 핸들러에게 이벤트를 다 처리하고 난 후 버블링을 중단하도록 명령할 수 있다. 그럴때 사용하는 이벤트 객체의 메서드인 event.stopPropagation()을 알아보자

event.stopPropagation()

  • 그냥 원하는 화면 요소의 이벤트만 신경 쓰고 싶을 때 사용한다.

    event.stopPropagation()는 이벤트 버블링의 경우에는 클릭한 요소의 이벤트만 발생시키고 상위 요소로 이벤트를 전달하는 것을 방해한다. 그리고 이벤트 캡쳐의 경우에는 클릭한 요소의 최상위 요소의 이벤트만 동작시키고 하위 요소들로 이벤트를 전달하지 않는다.

예제

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

이벤트 캡처링 (Event Capturing)

이벤트 버블링과 반대 방향으로 진행되는 이벤트 전파 방식. 특정 이벤트가 발생했을 때 최상위 요소인 body 태그에서 해당 태그를 찾아 내려간다.

예제

<body>
	<div class="one">
		<div class="two">
			<div class="three">
			</div>
		</div>
	</div>
</body>
var divs = document.querySelectorAll('div');
divs.forEach(function(div) {
	div.addEventListener('click', logEvent, {
		capture: true // default 값은 false
	});
});

function logEvent(event) {
	console.log(event.currentTarget.className);
}
  • addEventListener() API에서 옵션 객체에 capture:true를 설정해주면 된다. 그러면 해당 이벤트를 감지하기 위해 이벤트 버블링과 반대 방향으로 탐색한다.
  • three class를 갖는 div를 클릭했을 때 결과

출처 및 참고

https://ko.javascript.info/bubbling-and-capturing#ref-1066

https://joshua1988.github.io/web-development/javascript/event-propagation-delegation/

profile
Slow and Steady Wins the Race

0개의 댓글