이벤트엔 버블링 이외에도 ‘캡처링(capturing)’ 이라는 흐름이 존재합니다.
실제 코드에서 자주 쓰이진 않지만, 상황에 따라 필요할 수도 있으니 간단하게 살펴봅시다.
먼저, 표준 DOM 이벤트에서 정의한 이벤트 흐름에는 3가지 단계가 있습니다.
타깃 단계는 이벤트 객체의 target 프로퍼티가 되는 요소에 등록되어있던 이벤트 핸들러가 동작하는 단계인데, 쉽게 생각해서 가장 처음 이벤트 핸들러가 동작하게 되는 순간이라고 생각하시면 됩니다.
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<title>JS with Codeit</title>
</head>
<body>
<div id="content">
<h1 id="title">오늘 할 일</h1>
<ol id="list">
<li class="item">자바스크립트 공부</li>
<li class="item">독서</li>
</ol>
</div>
<script src="index.js"></script>
</body>
</html>
만약 위 코드에서 자바스크립트 공부를 클릭한다면, 버블링은 li
태그 부터, ol
태그, div
태그, body
태그, html
태그, document
, window
객체로 이벤트가 전파가 된다는 거 알고 계시죠?
캡쳐링은 이벤트가 발생하면 가장 먼저, 그리고 버블링의 반대 방향으로 진행되는 이벤트 전파 방식입니다.
이벤트가 발생하면 가장 먼저 window
객체에서부터 target
까지 이벤트 전파가 일어납니다. (캡쳐링 단계)
그리고 나서 타깃에 도달하면 타깃에 등록된 이벤트 핸들러가 동작하고, (타깃 단계)
이후 다시 window
객체로 이벤트가 전파됩니다. (버블링 단계)
이런 과정을 통해 각 요소에 할당된 이벤트 핸들러가 호출되는데요.
캡쳐링 단계에서 이벤트를 발생시켜야 하는 일은 매우 드문 경우입니다. 보통 타깃 단계에서 target
에 등록된 이벤트 핸들러가 있으면 해당 이벤트 핸들러가 먼저 동작한 이 후에 버블링 단계에서 각 부모 요소에 등록된 이벤트 핸들러가 있으면 그 때 해당 이벤트 핸들러가 동작하는 것이 일반적인데요.
하지만 상황에 따라서는 캡쳐링 단계에서 부모 요소의 이벤트 핸들러를 동작시켜야 할 수도 있겠죠? 캡쳐링 단계에서 이벤트 핸들러를 동작시키려면, addEventListener
에 세번째 프로퍼티에 true
또는 { capture:true }
를 전달하면 됩니다.
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<title>Codeit Acid Rain</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<div>DIV
<ul>UL
<li>LI</li>
</ul>
</div>
<script>
for (let elem of document.querySelectorAll('*')) {
elem.addEventListener("click", e => alert(`캡쳐링 단계: ${elem.tagName}`), true);
elem.addEventListener("click", e => alert(`버블링 단계: ${elem.tagName}`));
}
</script>
</body>
</html>
body * {
margin: 10px;
padding: 10px;
background-color: rgba(150, 0, 255, 0.15);
}
DIV클릭시 : 캡쳐링 단계: HTML > 캡쳐링 단계: BODY > 캡쳐링 단계: DIV > 버블링 단계: DIV > 버블링 단계: BODY > 버블링 단계: HTML
UL 클릭시 : 캡쳐링 단계: HTML > 캡쳐링 단계: BODY > 캡쳐링 단계: DIV > 캡쳐링 단계: UL > 버블링 단계: UL > 버블링 단계: DIV > 버블링 단계: BODY > 버블링 단계: HTML
LI 클릭시: 캡쳐링 단계: HTML > 캡쳐링 단계: BODY > 캡쳐링 단계: DIV > 캡쳐링 단계: UL > 캡쳐링 단계: LI > 버블링 단계: LI > 버블링 단계: UL > 버블링 단계: DIV > 버블링 단계: BODY > 버블링 단계: HTML