자바스크립트 - 이벤트 버블링과 이벤트 캡쳐

front_pica·2021년 5월 16일
1

이벤트 등록

이벤트 버블링을 알아보기에 앞서서 이벤트 등록을 어떻게 하는지부터 알아야 한다.
여기서 이벤트 등록이란 웹 애플리케이션에서 사용자의 입력을 받기위해 필요한 기능이라고 한다.
아래의 코드를 보시면


<button class="button">확인<button>

...


<script>
const button = document.querySelector('.button');
button.addEventListener('click', sayOk);

function sayOk() {
  console.log("ok");
}
</script>

button 클래스의 이름을 가진 dom요소를 지정하여 click이벤트를 달아 놓았고 이를 클릭해보면
콘솔창에 ok라는게 찍히는게 확인 됩니다.

이처럼 addEventListener() 웹 api는 웹 개발자들이 화면에 동적인 기능을 추가하기 위해 자연스럽게 사용하게 되는 기본적인 기능입니다. 여기서 브라우저는 어떻게 이벤트의 발생을 감지했을까요?
정답은 바로 브라우저가 앞으로 설명할 2가지 방식을 통해 감지를 하게 됩니다.

이제 본격적으로 이벤트 버블링과 캡쳐를 알아갈 수 있는 단계가 되었습니다!
더 알아보도록 합시다.

1. 이벤트 버블링이란?

DOM 요소에서 이벤트가 발생했을 때, 거기에 등록된 이벤트 리스너 함수가 있으면 실행을 시도한다. 그리고 이벤트는 부모 요소를 통해 DOM 트리 위쪽으로 전파(bubbled up)되며 거쳐가는 DOM 요소마다 같은 일(이벤트 리스너 확인 및 실행)이 반복된다. 이 버블링은 최상위 요소인 document까지 진행된다. 이벤트 버블링은 이벤트 위임(delegation) 메카니즘 안에 있다.

한줄 요약 : DOM 이벤트가 상위 요소(element)로 전파되는 현상

코드로 알아보면

<body>
  <div class="one">
    <div class="two">
      <div class="three">
      </div>
    </div>
  </div>
</body>
const divBlocks = document.querySelectorAll('div');
divBlocks.forEach(()=> {
  div.addEventListener('click', showClassName);
})

function showClassName(e) {
  console.log(e.currentTarget.className);
}

위 코드는 세 개의 div 태그에 모두 클릭 이벤트를 등록하고 클릭 했을 때 logEvent 함수를 실행시키는 코드입니다. 여기서 위 코드에서 최하위 div 태그

<div class="three"></div>

를 클릭하면 아래와 같은 결과가 실행됩니다.

왜 하나만 클릭했는데 세개가 찍힐까요?

그 이유는 브라우저가 이벤트를 감지하는 방식 때문입니다.
브라우저는 특정 화면 요서에서 이벤트를 발생했을 때 그 이벤트를 최상위에 있는 화면 요소까지 이벤트를 전파시킵니다. 따라서, three -> two -> one 순서대로 div태그에 등록된 이벤트들이 실행됩니다.
마찬가지로 two를 클릭하면 two -> one 이렇게 실행됩니다.

이렇게 하위에서 상위 요소로 이벤트 전파 방식을 이벤트 버블링(Event Bubbling)이라고 합니다.

2. 이벤트 캡쳐란?

이벤트 캡쳐는 이벤트 버블링 설명과 동일하지만, 정 반대의 방향으로 작동하는 방식입니다.

한줄 요약 : DOM 이벤트가 하위 요소(element)로 전파되는 현상

코드로 알아보면

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

function showClassName(e) {
  console.log(e.currentTarget.className);
}

addEventListener() api에서 옵션 객체에 capture: true로 설정해 주시면 됩니다.
이렇게 하면 아래와 같이 이벤트 버블링과는 반대의 방향으로 전파되게 됩니다.

3. event.stopPropagation()

나는 클릭한것만 나오게 하고싶은데 버블링도싫고 캡쳐도 싫어 하시는 분들을 위한 이벤트 요소입니다.

function showClassName(e) {
  e.stopPropagation();
  console.log(e.currentTarget.className);
}

이렇게 사용하게 되면 전파현상을 막으면서 본인의 것만 출력하게 할 수 있다.

참고 사이트
https://joshua1988.github.io/web-development/javascript/event-propagation-delegation/

profile
한걸음씩

0개의 댓글