이벤트 버블링 캡처링

H.GOO·2023년 1월 6일
1

웹개발 이론 공부

목록 보기
1/5

🪴 표준 DOM 이벤트

표준 DOM 이벤트에서 정의한 이벤트 흐름엔 3가지 단계가 있다.

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

<td> 를 클릭하면
1. 이벤트가 최상위 조상에서 시작해 아래로 전파되고(캡처링 단계),
2. 이벤트가 타깃 요소에 도착해 실행된 후(타깃 단계),
3. 다시 위로 전파된다(버블링 단계).

공식적으론 총 3개의 이벤트 흐름이 있지만, 이벤트가 실제 타깃 요소에 전달되는 단계인 ‘타깃 단계’(두 번째 단계)는 별도로 처리되지 않는다. 캡처링과 버블링 단계의 핸들러는 타깃 단계에서 트리거된다.



🪴 예시

<div onClick={() => alert('부모 태그')}>
  부모태그
  <div onClick={() => alert('자식 태그')}>
    자식태그
  </div>
</div>

부모태그 클릭 시 "부모 태그"
자식태그 클릭 시 "부모 태그" => "자식 태그"

이처럼 자식 태그를 클릭했지만 부모 태그에 할당된 이벤트가 동작하는 것을 이벤트 버블링 이라고 한다.



🪴 버블링

버블링의 원리

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

버블링 이름 뜻

이벤트가 제일 깊은 곳에 있는 요소에서 시작해 부모 요소를 거슬러 올라가며 발생하는 모양이 마치 물속 거품(bubble)과 닮았기 때문에 다음과 같이 부른다.



🪴 캡처링

캡처링 단계를 이용해야 하는 경우는 흔치 않고 대부분의 이벤트는 버블링 이벤트이다. (focus 이벤트 제외)

캡처링 이벤트를 설정해주는 방법

// javascript
elem.addEventListener(..., {capture: true})  // capture 옵션을 true로 설정
elem.addEventListener(..., true)  // 생략 가능

// jsx
<div onClickCapture={...} />


🪴 event.eventPhase

event.eventPhase 프로퍼티를 이용하면 현재 발생 중인 이벤트 흐름의 단계를 알 수 있다.

Event.NONE (0) : 이 이벤트는 현재 처리 중이 아닌 경우
Event.CAPTURING_PHASE (1) : 캡처링 단계
Event.AT_TARGET (2) : 타겟 단계
Event.BUBBLING_PHASE (3) : 버블링 단계


event.eventPhase 버블링 예시

// 버블링
<div className="최상위" onClick={e => console.log(`최상위 ${e.eventPhase}`)}>
  최상위 요소
  <div className="중위" onClick={e => console.log(`중위 ${e.eventPhase}`)}>
    중위 요소
    <div className="최하위" onClick={e => console.log(`최하위 ${e.eventPhase}`)}>
      최하위 요소
    </div>
  </div>
</div>

최상위 클릭 시 "최상위 3"
중위 클릭 시 "중위 3" => "최상위 3"
최하위 클릭 시 "최하위 3" => "중위 3" => "최상위 3"


event.eventPhase 캡처링 예시

// 캡처링 후에 이어지는 버블링
<div className="최상위" onClickCapture={e => console.log(`최상위 ${e.eventPhase}`)}>
  최상위 요소
  <div className="중위" onClickCapture={e => console.log(`중위 ${e.eventPhase}`)}>
    중위 요소
    <div className="최하위" onClickCapture={e => console.log(`최하위 ${e.eventPhase}`)}>
      최하위 요소
    </div>
  </div>
</div>

최상위 클릭 시 "최상위 1"
중위 클릭 시 "최상위 1" => "중위 1"
최하위 클릭 시 "최상위 1" => "중위 1" => "최하위 1"


event.eventPhase 캡처링 후 버블링 예시

// 캡처링 후에 이어지는 버블링
<div className="최상위" onClick={e => console.log(`최상위 ${e.eventPhase}`)} onClickCapture={e => console.log(`최상위 ${e.eventPhase}`)}>
  최상위 요소
  <div className="중위" onClick={e => console.log(`중위 ${e.eventPhase}`)} onClickCapture={e => console.log(`중위 ${e.eventPhase}`)}>
    중위 요소
    <div className="최하위" onClick={e => console.log(`최하위 ${e.eventPhase}`)} onClickCapture={e => console.log(`최하위 ${e.eventPhase}`)}>
      최하위 요소
    </div>
  </div>
</div>

최상위 클릭 시 "최상위 1" => "최상위 3"
중위 클릭 시 "최상위 1" => "중위 1" => "중위 3" =>"최상위 3"
최하위 클릭 시 "최상위 1" => "중위 1" => "최하위 1" => "최하위 3" => "중위 3" => "최상위 3"



🪴 버블링 및 캡처링 중단하기

onClick 속성으로 막기

// 캡처링 후에 이어지는 버블링 예시 코드
const stopEvent = (e) => {
  e.stopPropagation();
};

<div className="최상위" onClick={e => console.log(`최상위 ${e.eventPhase}`)} onClickCapture={e => console.log(`최상위 ${e.eventPhase}`)}>
  최상위 요소
  // 여기서 중위 요소의 onClick 또는 onClickCapture 동작 함수를 e.stopPropagation()로 변경
  <div className="중위" onClick={stopEvent} onClickCapture={stopEvent}>
    중위 요소
    <div className="최하위" onClick={e => console.log(`최하위 ${e.eventPhase}`)} onClickCapture={e => console.log(`최하위 ${e.eventPhase}`)}>
      최하위 요소
    </div>
  </div>
</div>

event.stopPropagation() 이 위쪽으로 일어나는 버블링 또는 아래쪽으로 일어나는 캡처링을 막아준다.

CSS 속성으로 막기

마우스/터치 이벤트를 제거하고 싶은 요소에 아래 속성을 추가한다.

pointer-events: none;

/* none: 비활성화 */
/* auto: 활성화 */
/* inherit: 부모 요소로부터 상속 받는다. */


🪴 버블링 및 캡처링 활용

버블링

하위 요소에 각각 이벤트를 붙이지 않고 상위 요소에서 하위 요소의 이벤트들을 제어하는 방식으로 이벤트 버블링을 활용

<div onClick="결제">
  <svg>결제 아이콘</svg>  // 아이콘을 눌러도 상위 요소의 onClick 동작함.
</div>

캡처링

ie 낮은 버전에서는 작동하지 않아 캡처링은 실제코드에서 잘 사용되지는 않는다.

0개의 댓글