[JavaScript] 이벤트 캡쳐링 & 버블링
이벤트 전파 (Event Phase) - 캡쳐링, 버블링
브라우저에서 HTML 요소에 이벤트가 발생했을 때 어떤 흐름으로 전파하는지 알아보자.
이벤트의 흐름은 최상위 요소부터 이벤트 타겟 요소까지 전달하며 내려가고 (= 이벤트 캡쳐링),
다시 반대로 타겟 요소부터 최상위 요소까지 전달하며 올라온다. (= 이벤트 버블링)
<html>
<head>
<title>제목</title>
</head>
<body>
<main>
<div>
<p>
<span></span>
</p>
</div>
</main>
<script>
const $body = document.querySelector('body');
const $main = document.querySelector('main');
const $div = document.querySelector('div');
const $p = document.querySelector('p');
const $span = document.querySelector('span');
$body.addEventListener('click', function() {
console.log('body 태그 클릭');
})
$main.addEventListener('click', function() {
console.log('main 태그 클릭');
})
$div.addEventListener('click', function() {
console.log('div 태그 클릭');
})
$p.addEventListener('click', function() {
console.log('p 태그 클릭');
})
$span.addEventListener('click', function() {
console.log('span 태그 클릭');
})
</script>
</body>
</html>
위와 같이 간단한 html 예제가 있고, 이 중 span 태그에 클릭 이벤트가 주어졌다고 가정해보자. 다시말해 html 부터 span 까지 이벤트가 타고 올라가서 타겟인 span의 이벤트가 실행되고, 다시 html 태그까지 내려오며 이벤트가 전파된다는 뜻이다.
javascript에서 span 태그에 이벤트 등록할 때 addEventListener() 메소드를 사용하는데, 이 메소드는 버블링(타겟에서 최상위로 전파)을 기본으로 동작한다. span 태그를 클릭하여 이벤트를 발생시킨 뒤 찍히는 로그를 확인해보면 아래와 같다.
span 태그 클릭
p 태그 클릭
div 태그 클릭
main 태그 클릭
body 태그 클릭
만약 버블링이 아니라 캡쳐링으로 동작하도록 설정하려면 옵션을 주면 된다. false가 디폴트 값이며, true로 설정하면 캡쳐링으로 동작하게 된다.
$body.addEventListener('click', function() {
console.log('capturing body 태그 클릭');
}, true)
$main.addEventListener('click', function() {
console.log('capturing main 태그 클릭');
}, true)
$div.addEventListener('click', function() {
console.log('capturing div 태그 클릭');
}, true)
$p.addEventListener('click', function() {
console.log('capturing p 태그 클릭');
}, true)
$span.addEventListener('click', function() {
console.log('capturing span 태그 클릭');
}, true)
$body.addEventListener('click', function() {
console.log('bubbling body 태그 클릭');
}, false)
$main.addEventListener('click', function() {
console.log('bubbling main 태그 클릭');
}, false)
$div.addEventListener('click', function() {
console.log('bubbling div 태그 클릭');
}, false)
$p.addEventListener('click', function() {
console.log('bubbling p 태그 클릭');
}, false)
$span.addEventListener('click', function() {
console.log('bubbling span 태그 클릭');
}, false)
위 예제 소스와 같이 버블링과 캡쳐링 모두 동작하도록 메소드를 각각 설정한 뒤, span 태그를 클릭하면 아래와 같이 로그가 찍힌다. 최상위에서 타겟으로 캡쳐링, 타겟에서 최상위로 버블링된 모습이다.
capturing body 태그 클릭
capturing main 태그 클릭
capturing div 태그 클릭
capturing p 태그 클릭
capturing span 태그 클릭
bubbling span 태그 클릭
bubbling p 태그 클릭
bubbling div 태그 클릭
bubbling main 태그 클릭
bubbling body 태그 클릭
event 객체
이벤트 객체에는 eventPhase 라는 객체가 있다. event.eventPhase는 현재 이벤트 흐름의 단계를 나타낸다.
Event.NONE (0) : 이벤트 처리중이 아닐 때
Event.CAPTURING_PHASE (1) : 이벤트 캡쳐링 진행중일 때 , 부모 객체를 통해 이벤트가 전파되고 있을 때
Event.AT_TARGET (2) : 이벤트 대상인 타겟에 도착했을 때
Event.BUBBLING_PHASE (3) : 이벤트 버블링 진행중일 때, 타겟 이벤트에서 역으로 부모로 전파되고 있을 때
이벤트 전파를 막고싶으면 어떻게 해야할까? event 객체 stopPropagation() web API 메소드를 사용하면 된다.
$span.addEventListener('click', function(event) {
event.stopPropagation();
console.log('bubbling span 태그 클릭');
}, false)
이렇게 이벤트 리스너 내에 사용하면 되고, 이 다음 작업부터 중단된다. 위 소스에서는 span의 bubbling 까지 진행되고 그 이후 이후 작업부터 중단된다.
비슷한 중단 API 메소드가 있다. Event.preventDefault() 인데, 어떤 이벤트에 대한 기본 동작을 실행하지 않도록 지정하는 메소드이다.
submit 이벤트를 막거나, anchor 태그의 기본 기능을 막을 때 자주 사용한다.
이 포스팅은 프론트엔드 날개달기: Vue, React 배우기 전에 꼭 알아야하는 지식 강의를 수강하며 작성되었습니다.
[지금 무료] 프론트엔드 날개달기: Vue, React 배우기 전에 꼭 알아야하는 지식 강의 | 짐코딩 - 인프
짐코딩 | 이 강의를 통해 Webpack, NPM 등 프론트엔드 개발자가 되기 전에 꼭 알아야할 지식을 탄탄히 다질 수 있습니다., 백그라운드 지식을 확실히 알아야,진짜 프론트엔드 개발자가 될 수 있어요
www.inflearn.com