이벤트 버블링과는 반대되는 성질을 가지고 있으며 상위요소에서 하위요소로 이벤트가 전달되는 특성입니다.
표준 DOM 이벤트에 정의된 이벤트 흐름엔 3가지 단계가 있습니다.
1. 캡처링 단계 - 이벤트가 하위 요소로 전파되는 단계
2. 타깃 단계 - 이벤트가 실제 타깃요소로 전달되는 단계
3. 버블링 단계 - 이벤트가 상위 요소로 전파되는 단계
출처 : https://ko.javascript.info/bubbling-and-capturing
위 사진을 참고하여 <td>
를 클릭하면 이벤트가 최상위 조상에서 시작해 아래로 전파되고 (캡처링), 이벤트가 타깃 요소에 도착해 실행 (타깃 단계), 다시 위로 전파됩니다 (버블링 단계).
캡처링
HTML -> BODY -> TABLE -> TBODY -> TR -> TD
타깃 요소
TD - 이벤트가 발생
버블링
TD -> TR -> TBODY -> TABLE -> BODY -> HTML
on<event>
, addEventListener(event, handler)
를 이용하여 할당된 핸들러는 캡처링에 대해 전혀 알 수 없습니다. 이 핸들러들은 타깃, 버블링 단계에 대해서만 동작합니다.
그렇기에 캡처링 단계에서 이벤트를 잡아내려면 addEventListener
의 capture 옵션을 true로 설정해야 합니다.
//아래 두 코드는 같은 방식으로 동작합니다.
.addEventListener(..., {capture: true});
.addEventListener(..., true);
cature 옵션은 두 가지 값을 가질 수 있습니다.
1. flase이면 (default) 핸들러는 버블링 단계에서 동작합니다.
2. true이면 핸들러는 캡처링 단계에서 동작합니다.
위 사진을 참고하여 코드를 작성해보고 캡처링과 버블링 타깃 단계에 대해 브라우저상 어떻게 동작하는지 알아보겠습니다.
<style>
body * {
margin: 10px;
border: 1px solid black;
}
</style>
<body>
<table>
<tbody>
<tr>
<td onclick="evevt()">td</td>
</tr>
</tbody>
</table>
<script>
for (let elem of document.querySelectorAll("*")) {
elem.addEventListener(
"click",
(e) => alert(`캡쳐링: ${elem.tagName}`),
true
);
elem.addEventListener("click", (e) => alert(`버블링: ${elem.tagName}`));
}
const target = document.querySelector("td");
const event = target.addEventListener("click", (e) =>
alert("타깃 요소 :" + e.target.tagName)
);
</script>
</body>
캡처링 단계로 상위요소<HTML>
에서 이벤트가 발생한 하위요소<TD>
순으로 동작한 후 반대로 하위요소에서 상위요소로 올라오는 버블링 단계가 실행되며 최초 타깃요소를 같이 호출하게 되는것을 볼 수 있습니다.
현재 발생 중인 이벤트의 흐름의 단계를 알 수 있는
event.eventPhase
프로퍼티가 존재합니다. 반환되는 정수값에 따라 이벤트 흐름의 실행 단계를 구분합니다.
addEventListener(..., true)
로 핸들러를 할당했다면 핸들러를 지울떄
removeEventListener(..., true)
를 사용하려 지워야하 하며, 같은 단계에 있어야 핸들러가 삭제됩니다.
같은 요소와 같은 단계에 설정한 리스너는 설정 순서대로 동작합니다.
특정요소에addEventListener
를 사용하여 한 단계에 여러 이벤트 핸들러를 설정하였다면 해당 핸들러는 설정한 순서대로 동작합니다..addEventListener(evnet, handler1); // 첫 번쨰로 트리거 됩니다. .addEventListener(evnet, handler2);
이벤트 캡처링 기능 참고 - JAVASCRIPT.INFO