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

강낭코딩·2025년 4월 13일
1

JavaScript

목록 보기
2/2
post-thumbnail

이벤트

무언가 일어났다는 신호!

마우스 이벤트

  • click
  • contextmenu : 마우스 오른쪽 버튼을 눌렀을 때
  • mouseover, mouseout, mousedown, mouseup, mousemove

폼 요소 이벤트

  • submit, focus

이벤트가 발생했을 때 실행되는 함수인 핸들러(handler)를 할당해야 한다

버블링

<div onClick={() => alert("div에 연결된 핸들러!")}>
	<span>click</span>
</div>

span 태그를 클릭했는데 div에 연결된 핸들러가 동작한다.

이것은 버블링(bubbling) 때문이다.

한 요소에 이벤트가 발생하면, 이 요소에 할당된 핸들러가 동작하고, 이어서 부모 요소의 핸들러가 동작한다. 가장 최상단의 조상 요소를 만날 때까지 이 과정이 반복되면서 요소 각각에 할당된 핸들러가 동작한다.

<form onClick="alert('form')">
  FORM
  <div onClick="alert('div')">
    DIV
    <p onClick="alert('p')">P</p>
  </div>
</form>

가장 안쪽의 <p>를 클릭하면 순서대로 다음과 같은 일이 발생한다

  1. <p>에 할당된 onclick 핸들러가 동작한다
  2. <div>에 할당된 onclick 핸들러가 동작한다
  3. <form>에 할당된 onclick 핸들러가 동작한다
  4. document 객체를 만날 때까지 각 요소에 할당된 onclick 핸들러가 동작한다

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

몇몇 이벤트를 제외하고 대부분의 이벤트는 버블링된다

target과 currentTarget

p 클릭 → target은 현재 클릭된 <p>가 되고, currentTarget은 <form>이 된다

div 클릭 → target은 현재 클릭된 <div>가 되고, currentTarget은 <form>이 된다

form 클릭 → target은 현재 클릭된 <form>이 되고, currentTarget은 <form>이 된다

target은 이벤트가 처음 발생한 요소, currentTarget은 현재 실행 중인 이벤트 핸들러가 붙어있는 요소이다. target은 변하지 않지만, currentTarget은 이벤트가 전파되면서 핸들러가 실행되는 요소에 따라 계속 변하는 게 핵심이다

버블링 중단하기

이벤트 버블링은 target 이벤트에서 <html> 요소를 거쳐 document 객체를 만날 때까지 각 노드에서 모두 발생한다. 모든 이벤트가 호출되는 것이다.

하지만 핸들러에게 이벤트를 완전히 처리하고 난 후 버블링을 중단하도록 명령할 수 있다.

이벤트 객체의 메서드인 event.stopPropagation()를 사용하면 된다

<form onClick="alert('form')">
  FORM
  <div onClick="alert('div')">
    DIV
    <p onClick="event.stopPropagation()">P</p>
  </div>
</form>

p를 클릭하면 아무일도 일어나지 않는다

캡처링

표준 DOM 이벤트에서 정의한 이벤트 흐름 3가지

  1. 캡처링 단계 - 이벤트가 하위 요소로 전파되는 단계
  2. 타깃 단계 - 이벤트가 실제 타킷 요소에 전달되는 단계
  3. 버블링 단계 - 이벤트가 상위 요소로 전파되는 단계

캡처링 단계에서 이벤트를 잡아내려면 addEventListnercapture 옵션을 true로 설정해야 한다

for (let elem of document.querySelectorAll("*")) {
  elem.addEventListener(
    "click",
    (event) => alert(`캡처링 : ${event.currentTarget.tagName}`),
    { capture: true }
  );
  elem.addEventListener("click", (event) =>
    alert(`버블링 : ${event.currentTarget.tagName}`)
  );
}

p를 클릭하면 다음과 같은 순서로 이벤트가 전달된다

  1. HTMLBODYFORMDIV (캡처링 단계)
  2. P (타깃 단계)
  3. DIVFORMBODYHTML (버블링 단계)

정리

이벤트 버블링을 이용하여 이벤트 위임 패턴을 만들 수 있다

예시) 반복되는 자식 요소의 이벤드 핸들러를 부모 요소에 옮겨놓고, 이벤트가 어디서 일어났는지 event.target으로 파악한 후 해당 자식 요소에서 핸들러 실행. 반복되는 리스트나 테이블에 활용할 수 있음

target과 currentTarget을 정확히 파악하여 부모 요소에서 이벤트를 한꺼번에 처리하는 최적화된 코드를 만들 수 있다

0개의 댓글