자바스크립트에서 이벤트 버블링과 캡처링은 이벤트 모델에서 이벤트가 발생한 요소로부터 상위 요소로 전파되는 방식을 뜻합니다.
HTML에서 이벤트는 일반적으로 아래 3가지 단계를 거쳐 전파됩니다.
캡처링 단계: 이벤트가 발생한 요소의 가장 상위 요소부터 시작하여 이벤트가 발생한 요소까지 이벤트가 전파됩니다. 이 단계에서 이벤트를 캡처링하려면, addEventListener() 메서드의 3번째 인자로 true를 전달합니다.
대상 단계(타깃 단계): 이벤트가 발생한 요소에 이벤트 핸들러가 호출됩니다.
버블링 단계: 이벤트가 발생한 요소에서 시작하여 상위 요소까지 이벤트가 전파됩니다. 버블링 단계에서 이벤트를 캡처링하려면, addEventListener() 메서드의 3번째 인자로 false를 전달하거나 인자를 전달하지 않습니다.
<!DOCTYPE html>
<html>
<head>
<title>Event Capturing Example</title>
</head>
<body>
<div id="outer" style="background-color: yellow; width: 300px; height: 200px;">
<div id="inner" style="background-color: red; width: 200px; height: 100px;">
<button id="button">Click Me</button>
</div>
</div>
<script>
var outer = document.getElementById("outer");
var inner = document.getElementById("inner");
var button = document.getElementById("button");
outer.addEventListener("click", function() {
console.log("outer captured");
}, true);
inner.addEventListener("click", function() {
console.log("inner captured");
}, true);
button.addEventListener("click", function() {
console.log("button clicked");
});
</script>
</body>
</html>
위 태그는 outer > inner > button 요소 순으로 감싸져 있습니다.
outer 요소와 inner 요소에서는 이벤트 캡처링을 사용하여 button 클릭 이벤트가 전파되는 동안 각각 "outer captured"과 "inner captured" 메시지를 출력합니다.
따라서 위의 예제에서 버튼을 클릭하면 "outer captured" > "inner captured" > "button clicked" 순으로 출력됩니다. 이벤트 캡처링으로 인해 이벤트가 가장 상위 요소부터 하위 요소로 전파되는 것을 보여주는 것이죠.
<!DOCTYPE html>
<html>
<head>
<title>Event Capturing Example</title>
</head>
<body>
<div id="outer" style="background-color: yellow; width: 300px; height: 200px;">
<div id="inner" style="background-color: red; width: 200px; height: 100px;">
<button id="button">Click Me</button>
</div>
</div>
<script>
var outer = document.getElementById("outer");
var inner = document.getElementById("inner");
var button = document.getElementById("button");
outer.addEventListener("click", function() {
console.log("outer captured");
},false); //false 생략가능
inner.addEventListener("click", function() {
console.log("inner captured");
},false); //false 생략가능
button.addEventListener("click", function() {
console.log("button clicked");
},false); //false 생략가능
</script>
</body>
</html>
위 태그도 outer > inner > button 요소 순으로 감싸져 있습니다.
하지만 addEventListener() 마지막 파라미터가 "false"입니다. addEventListener() 메서드의 세 번째 파라미터를 생략하면 기본값으로 false, 즉 버블링을 사용합니다.
따라서 위의 예제에서 버튼을 클릭하면 "button clicked" > "inner captured" > "outer captured" 순으로 출력됩니다. 이벤트 버블링으로 인해 이벤트가 가장 하위 요소부터 상위 요소로 전파되는 것을 보여주는 예입니다.
이벤트 버블링을 활용하면 상위 요소에도 이벤트 위임이 가능하기 때문에, 이벤트 핸들러의 중복을 방지해 코드가 간결해지는 장점이 있습니다. 하지만 보통은 제가 원하는 요소만 주고 싶은 경우가 많지 않을까요..?
이벤트 객체의 메서드인 .stopPropagation()
를 사용
stopPropagation()은 해당 이벤트가 전파되는걸 막음. 단 현재 이벤트 한번은 처리됨
요소에 할당된 다른 핸들러의 동작도 막으려면 .stopImmediatePropagation()
을 사용
stopImmediatePropagation() 메소드를 호출하면, 이벤트 전파와 더불어 형제 이벤트 실행을 중지함
.preventDefault( )
는 이벤트 전파 뿐만 아니라, 기본 이벤트 동작 수행을 막음
<a href=”url”>
의 링크 기능을 막거나, <form>
태그의 submit 이벤트를 취소할 때 등 사용
.stopPropagation( )
: 이벤트 전파 중지.stopImmediatePropagation( )
: 이벤트 전파 중지 + 형제 이벤트 실행 중지.preventDefault( )
: 이벤트 전파 중지 + 형제 이벤트 실행 중지 + 이벤트 기본 동작 중지참고
https://accurate-baker-e9f.notion.site/0331_-a143941aea5746dc920d1af8c4186274