[JS]이벤트 전파 캡쳐링, 버블링

Kyle·2020년 11월 20일
1

web

목록 보기
2/5

addEventListener

addEventListener

target.addEventListener(type, listener[, useCapture]);

addEventListener의 구문이다.

type : 이벤트의 유형

listener : 이벤트가 발생했을 때 실행하는 콜백함수

useCapture : boolean 값을 받는다. 말 그대로 capturing단계의 이벤트를 캐치 하느냐 마느냐이다. default 값은 false로 bubbling 단계의 이벤트를 캐치한다.

그러면 capturingbubbling은 무엇일까?

이벤트 전파 (event propagation)

W3C UIEvents specification에서 이벤트 흐름에 대해 설명해준 그림이다. 이 그림만 기억하면 버블링,캡쳐링에 대해 이해하기 어렵지 않다.

HTML에서 이벤트가 발생하면 1. 캡쳐링 단계 -> 이벤트 타켓 단계 -> 버블링 단계의 순서대로 이벤트가 전파된다.
이때 useCapture에 따라 어느 단계에 이벤트를 적용시킬지 결정해준다.

무조건 이벤트가 발생하면 window부터 시작해 target지점 까지 capturing phase를 거치고 target phase를 거친뒤 다시 bubbling phase가 window까지 발생한다.

아래 예를 보고 이해해보자.

캡쳐링, 버블링

각각의 상자를 누르면 console에 first,second,third가 출력된다.

<!DOCTYPE html>
<html lang="en" class="html">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <link rel="stylesheet" href="style.css" />
  </head>
  <body class="body">
    <div class="first">
      first
      <div class="second">
        second
        <div class="third">third</div>
      </div>
    </div>
    <script src="./test.js"></script>
  </body>
</html>

이벤트 캡쳐링

HTML에서 이벤트가 발생되면 window부터 target까지 이벤트 캡쳐링 phase가 먼저 진행된다.

addEventListeneruseCapture의 속성이 true로 설정된 이벤트들은 이 단계에서 콜백함수를 실행시킨다.

first.addEventListener('click', () => {
  console.log('first');
});
second.addEventListener(
  'click',
  () => {
    console.log('second');
  },
  true
);
third.addEventListener('click', () => {
  console.log('third');
});

위의 코드를 먼저 예상해보자

결과

third를 클릭했는데 second가 먼저 출력된 것을 확인할 수 있다.
useCapture의 default값은 false로 버블링 단계에서 이벤트를 실행하게 돼 있지만, second의 useCapture를 true로 설정해준 결과이다.

  1. 캡쳐링 phase: second의 이벤트가 먼저 실행
  2. target phase: third의 이벤트
  3. 버블링 phase: first의 이벤트

이벤트 버블링

캡쳐링을 보았으니 아래의 코드도 예상해보자

first.addEventListener('click', () => {
  console.log('first');
});
second.addEventListener('click', () => {
  console.log('second');
});
third.addEventListener('click', () => {
  console.log('third');
});

결과

이벤트 전파에 따른 실행순서

  1. capturing phase: useCapture속성이 true로 설정된 이벤트가 없기 때문에 아무일도 없다.
  2. target phase: target인 third의 이벤트가 실행된다.
  3. bubbling phase: first,second의 useCapture이 default인 false이므로 버블링 단계에서 실행된다.

remove event

이벤트를 지우는 테스트 해봤다.

const first = document.querySelector(".first");
first.removeEventListener("click", handleClick);

평소대로 위에 removeEventListener를 이용해 event를 삭제했는데, bubbling으로 설정했을 때는 event가 삭제됐지만 캡쳐링일 때는 삭제가 안되는 것이다.

그러다 발견한 사실이 addEventListener에서 설정한 useCapture과 같이 아래의 예제처럼 실행해 주어야 했다.

first.removeEventListener("click", handleClick, true);

마무리

캡처링과 버블링을 통해서 이벤트 위임(Event Delegation) 을 구현 할 수 있다. 이벤트 위임은 많은 리스트가 있거나 테이블에 td가 많을 경우 유용하게 사용될 수 있다.
또한 이벤트 전파를 멈추는 방법도 알아두어야 한다.

처음에 이벤트 캡쳐링과 버블링을 잘못 이해하고 블로그 포스팅도 잘못했었다.

결국 이벤트 캡쳐링과 버블링은 HTML의 이벤트 전파 단계 캡쳐링->target->버블링 단계중 어느단계에서 이벤트를 실행시켜주는것인지 결정하는 것이었다.

잘못 이해한 상태로 김버그님의 유튜브 버블링 캡쳐링을 보는데 버블링과 캡쳐링을 제대로 이해할 수 있었다.

참조 : https://www.youtube.com/watch?v=7gKtNC3b_S8

profile
Kyle 발전기

0개의 댓글