중첩된 엘리먼트들 중 어느 한 요소에 이벤트 핸들러를 등록하면 중첩된 엘리먼트들 모두 전파되는 현상을 말한다.
이런 현상을 HTML DOM API의 이벤트 전파(Event Propagation)라 말하고 두 가지 방식으로 구분된다.
- 이벤트 버블링 : 이벤트가 발생한 요소부터 window 까지 이벤트를 전파한다.(👆)
- 이벤트 캡처링 : window 로부터 이벤트가 발생한 요소까지 이벤트를 전파한다.(👇)
둘의 차이는 방향에 있다. 상위 계층요소에서 하위로 간다면 이벤트 캡처링 그 반대인 하위 요소에서 상위 계층요소로 전파된다면 그것을 이벤트 버블링이라고 말한다.
이벤트 버블링
<body>
<div class="one">
<div class="two">
<div class="three">
</div>
</div>
</div>
</body>
var divs = document.querySelectorAll('div');
divs.forEach(function(div) {
div.addEventListener('click', logEvent);
});
function logEvent(event) {
console.log(event.currentTarget.className);
}
위 html과 JS를 렌더링 후에 div 태그 한 개만 클릭하면 왜 3개의 이벤트가 발생되는 걸까요?
그 이유는 브라우저가 이벤트를 감지하는 방식 때문입니다.
브라우저는 특정 화면 요소에서 이벤트가 발생했을 때 그 이벤트를 최상위에 있는 화면 요소까지 이벤트를 전파시킵니다.
따라서, 클래스 명 three -> two -> one 순서로 div 태그에 등록된 이벤트들이 실행됩니다. 마찬가지로 two 클래스를 갖는 두 번째 태그를 클릭했다면 two -> one 순으로 클릭 이벤트가 동작하겠죠.
여기서 주의해야 할 점은 각 태그마다 이벤트가 등록되어 있기 때문에 상위 요소로 이벤트가 전달되는 것을 확인할 수 있습니다. 만약 이벤트가 특정 div 태그에만 달려 있다면 위와 같은 동작 결과는 확인할 수 없습니다.
이벤트 캡처링
이벤트 버블링에서 방향만 바뀐 형태이다.
하위 요소를 클릭하면 상위 요소까지 이벤트가 전파되는 현상이 일어난다.
해결법
이벤트 버블링과 캡처링은 특징이지 절때 에러가 아니다.
하지만 이런 현상은 웹 개발할때 구현을 방해하는 요소가 되기도 한다. 그럴때 해결할 방법은
WEB API중 하나인 event.stopPropagation()를 사용하는 방법이다.
사용 방법은 간단하다.
이벤트를 발생시키고 버블링 혹은 캡처링이 일어나지 않도록 하는 요소에
// 이벤트 버블링 예제
divs.forEach(function(div) {
div.addEventListener('click', logEvent);
});
function logEvent(event) {
event.stopPropagation();
console.log(event.currentTarget.className); // three
}
위 코드와 이벤트가 실행되는 함수에 작성만 해주면된다..
캡처링에 경우에는 이벤트 핸들러를 부여할때 capture : true를 추가해주면 된다.
https://joshua1988.github.io/web-development/javascript/event-propagation-delegation/#%EC%9D%B4%EB%B2%A4%ED%8A%B8-%EB%B2%84%EB%B8%94%EB%A7%81---event-bubbling
'WEB > JavaScript' 카테고리의 다른 글
[JS] Formik (0) | 2021.06.13 |
---|---|
[JS] 함수를 호출하는 call / apply / bind 차이점 (0) | 2021.06.08 |
[JS] 이벤트 루프(Event Loop) (0) | 2021.06.07 |
[JS] 자바스크립트 동작원리 (0) | 2021.06.07 |
[JS] 메모리 힙과 콜스택 (0) | 2021.06.07 |