TIL 2021-05-18 (이벤트 버블링, 이벤트 캡쳐링)

nyongho·2021년 5월 18일
0

오늘 배운 내용

목록 보기
23/40

TIL


TIL List

  • 이벤트 버블링이란?
  • 이벤트 캡쳐링이란?
  • 이벤트 버블링을 막는 방법

1) 이벤트 버블링

설명에 앞서 코드를 먼저 살펴보자.

<div onclick="alert('The DIV handler!')">
  DIV 태그
  <p>P 태그</p>
</div>

div > p 형식의 코드로 부모인 div 에게 onclick 메소드가 할당되었다.
하지만 그 안의 p 태그를 클릭하더라도 div 태그의 onclick 메소드가 실행되는 것을 알 수 있다.
이러한 현상을 바로 이벤트 버블링 이라고 한다.

이벤트 버블링은 엘리먼트에 이벤트가 발생하면 먼저 해당 엘리먼트의 핸들러를 실행시킨 후, 그의 부모 엘리먼트의 핸들러를 실행시키고, 또 그 위의 조상 엘리먼트들의 핸들러를 차례로 실행시킨다

이제 다음의 코드를 보고 p 태그를 누르면 어떤 현상이 일어날지 감이 올 것이다.

<form onclick="alert('form')">
  I'M Form
  <div onclick="alert('div')">
    I'm Div
    <p onclick="alert('p')">I'm P</p>
  </div>
</form>

맞다. p 알람 > div 알람 > form 알람 이 차례대로 울리게 된다.
만약 div 태그를 눌렀다면 div > form 순으로 알람이 울리게 된다.

그렇다면 왜 하나의 태그를 클릭해도 여러 개의 이벤트가 발생하는 것인가?

그 이유는 바로 "브라우저가 이벤트를 감지하는 방식" 때문이다.

브라우저는 특정 화면 요소에서 이벤트가 발생했을 때 그 이벤트를 최상위에 있는 화면 요소까지 이벤트를 전파시킨다.


2) 이벤트 캡쳐링

이벤트 캡쳐링은 이벤트 버블링의 반대다.

버블링이 아래에서 위로 올라가는 방식이었다면 캡쳐링은 위에서 아래로 내려가는 방식이다.

이벤트 캡쳐링의 이벤트를 catch 하려면 addEventListner 의 세번째 인자를 true 로 설정해야 한다.

기본적으로 addEventListener의 세 번째 요소를 작성하지 않으면 default 값이 false인데, false로 설정할 경우, 핸들러는 버블링 단계로 설정된다.

<form onclick="alert('form')">
  I'M Form
  <div onclick="alert('div')">
    I'm Div
    <p onclick="alert('p')">I'm P</p>
  </div>
</form>
for (let elem of document.querySelectorAll('*')) {
    elem.addEventListener("click", e => alert(elem.tagName));
}

위 코드에서 p 태그를 클릭하면 P > DIV > FORM > BODY > HTML 순으로 이벤트 버블링이 일어난다.

이제 addEventLister의 세번째 인자에 true 값을 넣어보자.

for (let elem of document.querySelectorAll('*')) {
    elem.addEventListener("click", e => alert(elem.tagName), true);
}

이제는 p 태그를 클릭하면 HTML > BODY > FORM > DIV > P 순서로 이벤트 캡쳐링이 일어난다.


3) 이벤트 버블링을 강제로 멈추는 방법

이벤트 버블링은 기본적으로 일어나는 현상이지만, 이를 강제로 멈추는 방법이 있다.

event.stopPropagation() 코드로 가능하다.

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

다음과 같이 p 태그에 event.stopPropagation() 를 주게 되면 더이상 버블링이 일어나지 않게 된다.

profile
두 줄 소개

0개의 댓글