오늘은 이벤트 버블링과 캡처링에 대해 다시 공부하면서,
관련 메서드 3가지를 정리해 보았습니다.
이벤트 버블링과 캡처링
이벤트 버블링 (Event Bubbling)
이벤트 버블링은 이벤트가 발생한 가장 아래(자식) 요소에서 시작하여, DOM 트리를 따라 점점 상위 요소로 전파되는 과정을 말합니다. 예를 들어, HTML 문서에서 버튼(button
)을 클릭하면 이벤트는 먼저 해당 button
에서 발생하고, 그 후 button
의 부모 요소로, 그 다음은 조상 요소로 순차적으로 이벤트가 전파됩니다.
<div>
<button>Click me!</button>
</div>
위의 예에서 버튼을 클릭하면, 클릭 이벤트는 먼저 button
에서 발생하고, 그 후 div
, 그리고 body
, html
요소로 차례로 전파됩니다.
이벤트 캡처링 (Event Capturing)
이벤트 캡처링은 이벤트 버블링과 반대 방향으로 진행됩니다. 이벤트가 발생하면 가장 상위 요소(document
)에서 시작하여, 발생한 요소의 방향으로 내려가면서 각 요소에 이벤트를 전달합니다. 즉, document
부터 시작하여 점차 이벤트가 발생한 요소까지 내려갑니다. 하지만 기본적으로 대부분의 이벤트 핸들러는 버블링 단계에서만 작동하고, 캡처링 단계에서는 작동하지 않습니다. 이벤트 리스너를 등록할 때 세번째 인자로 true 를 넘기면 캡처링 단계에서도 반응하도록 설정할 수 있습니다.
element.addEventListener('click', function(event) {
console.log('Captured!');
}, true); // true는 이벤트 리스너가 캡처링 단계에서 호출되어야 함을 의미합니다.
버블링 과 캡처링 동시 사용
버블링과 캡처링은 동시 사용도 가능합니다! 세번째 인자가 각각 false(기본값, 버블링사용), true(캡처링사용)인 이벤트리스너를 두 개 등록해주면 올라가고 내려오는 모든 이벤트를 캐치할 수 있다.
<div id="ancestor">
<div id="parent">
<div id="child">
</div>
</div>
</div>
const ancestor = document.querySelector("#ancestor");
const parent = document.querySelector("#parent");
const child = document.querySelector("#child");
let count = 1;
ancestor.addEventListener("click", (e) => console.log(`${count++}. ancestor`));
ancestor.addEventListener("click", (e) => console.log(`${count++}. ancestor`), true);
parent.addEventListener("click", (e) => console.log(`${count++}. parent`));
parent.addEventListener("click", (e) => console.log(`${count++}. parent`), true);
child.addEventListener("click", (e) => console.log(`${count++}. child`));
child.addEventListener("click", (e) => console.log(`${count++}. child`), true);
위와 같다면, 중첩요소 child 를 클릭할 경우 콘솔에
- ancestor clicked
- parent clicked
- child clicked
- child clicked
- parent clicked
- ancestor clicked
이런 순서로 콘솔이 찍히게 된다!
이벤트 관련 메소드 세가지
1. stopPropagation()
stopPropagation()
메서드는 현재 이벤트가 더 이상 전파되지 않도록 중단합니다.
이는 이벤트 버블링 또는 캡처링을 통해 상위 또는 하위 요소로 이벤트가 이동하는 것을 막습니다.
document.getElementById('inner').addEventListener('click', function(event) {
event.stopPropagation();
console.log('버블링이 일어나지 않을 것입니다');
});
위 예에서 #inner
요소에서 클릭 이벤트가 발생하면, 이벤트는 상위 요소로 버블링되지 않습니다.
2. stopImmediatePropagation()
stopImmediatePropagation()
메서드는 stopPropagation()
과 유사하게 이벤트가 더 이상 전파되지 않도록 중단하지만, 더 강력(?)합니다. 이 메서드는 현재 요소에 등록된 다른 이벤트 핸들러들까지도 실행되지 않도록 중단합니다.
document.getElementById('inner').addEventListener('click', function(event) {
event.stopImmediatePropagation();
console.log('첫번째 핸들러는 작동하지만');
});
document.getElementById('inner').addEventListener('click', function(event) {
console.log('두번째는 작동하지 않을 것 입니다.');
});
위 예에서 #inner
요소에 등록된 첫 번째 이벤트 핸들러가 stopImmediatePropagation()
을 호출하면, 두 번째 이벤트 핸들러는 실행되지 않습니다.
3. preventDefault()
preventDefault()
메서드는 이벤트의 기본 동작을 취소합니다.
이 메서드는 주로 폼 제출, 링크 이동, 키보드 입력 등의 브라우저의 기본 동작을 막고자 할 때 사용됩니다.
document.getElementById('my-link').addEventListener('click', function(event) {
event.preventDefault();
console.log('a 태그의 기본 동작은 막혔습니다.');
});
위 예에서 링크 클릭 시 브라우저가 다른 페이지로 이동하는 기본 동작이 취소됩니다.
종합
- stopPropagation()는 이벤트 버블링이나 캡처링을 중단합니다.
- stopImmediatePropagation()는 현재 요소에서 이벤트 전파 뿐만 아니라 다른 이벤트 핸들러의 실행까지 중단합니다.
- preventDefault()는 이벤트의 기본 동작을 취소합니다.
'javascript' 카테고리의 다른 글
[240513 TIL] 불변성 원칙과 순수 함수 (0) | 2024.05.13 |
---|---|
[240512 WIL] Hash Routing, History API (0) | 2024.05.12 |
[240508 TIL] Object.assign, 깊은 복사 (1) | 2024.05.08 |
[240507 TIL] Object.is (0) | 2024.05.07 |
[240504 WIL] query params (0) | 2024.05.04 |