이벤트 버블링 ( Event Bubbling )
이벤트 버블링이란 한 요소에 이벤트가 발생되면, 그 요소의 부모 요소의 이벤트도 같이 발생되는 이벤트 전파를 말한다. 왼쪽 그림에서처럼 가장 깊게 중첩된 요소 (3)에 이벤트가 발생했을 때 이벤트가 위로 (bubble up) 전파되어버린다.
그래서 3번 요소, 2번 요소, 1번요소에 그 이벤트에 대한 핸들러가 있다면 3번 요소에 핸들러가 실행되고 2번 요소에 핸들러, 1번요소에 핸들러 순으로 실행된다.
코드를 통해 살펴보면, 아래 3개가 중첩된 박스 영역에서 가장 자식 엘리먼트인 <p> 박스를 클릭하면 onclick 이벤트 스크립트가 <p> 뿐만 아니라 그의 부모인 <div>와 <form> 엘리먼트도 발생함을 볼 수 있다.
<form onclick="alert('form')">
FORM
<div onclick="alert('div')">
DIV
<p onclick="alert('p')">
P
</p>
</div>
</form>
See the Pen Untitled by Seio924 (@Seio924) on CodePen.
event.target 과 this ( event.currentTarget )
그렇다면 이벤트 버블링이 발생했을 때 어디서 이벤트가 발생했는지, 즉 내가 클릭한 곳이 어딘지 쉽게 알 수 있는 방법은 없을까? 우리는 event.target과 this(event.currentTarget)을 통해 이를 확인할 수 있다.
const form = document.querySelector('form');
const div = document.querySelector('div');
const p = document.querySelector('p');
form.onclick = function (event) {
event.target.style.backgroundColor = 'yellow';
setTimeout(() => {
alert("target = " + event.target.tagName + ", this=" + this.tagName);
event.target.style.backgroundColor = ''
}, 0);
};
See the Pen Bubbling2 by Seio924 (@Seio924) on CodePen.
가장 자식 엘리먼트인 <p> 박스를 클릭했을 때, event.target은 <p> 요소를, this(또는 event.currentTarget)는 부모 요소인 <form>을 가리킨다. 이를 통해 event.target은 클릭된 요소 자체를, this(event.currentTarget)는 이벤트 리스너가 부착된 부모 요소를 나타낸다는 것을 알 수 있다. 따라서 우리는 부모 요소 핸들러에서 어디서 이벤트가 발생했는지 알 수 있는 것이다.
💡 요약
event.target : 실제 이벤트가 시작된 '타깃' 요소이다.
this (event.currentTarget) : '현재' 요소로, 현재 실행 중인 핸들러가 할당된 요소를 참조한다.
이벤트 버블링 중단하기
이벤트 버블링은 타깃 이벤트에서 시작해서 요소를 거쳐 document 객체를 만날 때까지 각 노드에서 모두 발생한다. 몇몇 이벤트는 window 객체까지 거슬러 올라가기도 하는데, 이 때도 모든 핸들러가 호출된다.
이러한 상황에서 우리는 event.stopPropagation() 메소드를 사용하여 핸들러에게 이벤트를 완전히 처리하고 난 후 버블링을 중단하도록 명령할 수 있다.
<form onclick="alert('form')">
FORM
<div onclick="alert('div')">
DIV
<p onclick="event.stopPropagation()">
P
</p>
</div>
</form>
See the Pen Bubbling3 by Seio924 (@Seio924) on CodePen.
이렇게 해주면 <p> 요소를 클릭해도 event bubbling이 발생하지 않기에 부모 요소들의 핸들러도 호출이 되지 않게 된다.
이벤트 캡처링 ( Event Capturing )
이벤트 캡처링은 한 요소에 이벤트가 발생되면, 그 요소의 자손 요소의 이벤트도 같이 발생되는 이벤트 전파를 말한다. 버블링과 반대로 제일 상단에 있는 요소에서 아래로 이벤트가 내려오는 것이다.
이벤트의 3단계 흐름 ( flow )
이벤트 캡처링을 더 자세히 이해하기 위해, 이벤트의 3단계 흐름을 살펴보자.
1. 캡처링 단계 : 이벤트가 하위 요소로 전파되는 단계
2. 타깃 단계 : 이벤트가 실제 타깃 요소에 전달되는 단계
3. 버블링 단계 : 이벤트가 상위 요소로 전파되는 단계
HTML 문서에서 <td> 요소를 클릭했을 때, 이벤트는 위와 같은 방식으로 흐르게 된다.
1. <td> 요소를 클릭하면 이벤트가 최상위 조상에서 시작해 아래로 전파된다. (캡처링 단계)
2. 이벤트가 타깃 요소에 도착해 실행된다. (타깃 단계)
3. 다시 위로 전파된다. (버블링 단계)
이런 과정을 통해 요소에 할당된 이벤트 핸들러가 호출된다.
코드로 이벤트 흐름 살펴보기
버블링의 흐름을 알기 위해 중첩된 요소들에 핸들러를 넣어서 확인했다. 그럼 캡처링의 흐름을 확인하려면 어떻게 해야 할까?
elem.addEventListener(..., { capture: true })
//아니면, 아래 같이 {capture: true} 대신, true를 써줘도 됩니다.
elem.addEventListener(..., true)
addEventListener의 capture 옵션을 true로 설정해야한다.
See the Pen Capturing by Seio924 (@Seio924) on CodePen.
요소를 클릭하면 가장 처음 캡처링이 진행되기에
1. 캡쳐링: HTML => .... => DIV 로 진행되며 (캡처링 단계)
2. 버블링: DIV => .... HTML 로 진행됩니다.(버블링 단계)
이런 식으로 진행된다.
※ 이벤트 흐름에서 2단계인 타켓 단계는 별도로 처리가 되지 않는다.
'Language > JavaScript' 카테고리의 다른 글
[ JS ] Call & Bind & Apply 완벽 정리 (0) | 2024.10.10 |
---|---|
[ JS ] 자바스크립트 this 키워드 정복하기 (0) | 2024.10.09 |
[ JS ] 자바스크립트 타입 총정리 (0) | 2024.10.09 |
[ JS ] var, let, const ( + 변수 호이스팅 ) (2) | 2024.09.19 |