[TIL] 이벤트 버블링, 이벤트 캡쳐링, 해결 방법
Created By: 성희 배 Last Edited: Apr 24, 2020 6:58 PM Tags: cs
호텔 클로닝 사이드 프로젝트에서 발생한 문제이다.
자식 버튼을 누를 시에 부모의 이벤트가 호출되는 현상이 나타났다. 문제는 이벤트 버블링 때문이었다.
이벤트 버블링
- 하위 엘리먼트에 이벤트 발생 시 그 엘리먼트부터 상위 요소까지 이벤트가 전달되는 방식
- 위와 같은 형식이 있을 때,
li
를 클릭하게 되면li
→ul
→div
순으로 호출된다.
이벤트 캡쳐링
- 하위 엘리먼트에 이벤트 핸들러가 있을 때 상위 엘리먼트부터 이벤트가 발생 해 하위 엘리먼트까지 이벤트가 전달됨
- 똑같은 형식에
li
를 클릭 시ul
을 호출하고 싶을때,ul
의 이벤트 리스너에{capture : true}
로 우선순위를 부여할 수 있다.
이벤트 위임 (참고)
조상에 이벤트를 등록하여 조상이 하위 element에 이벤트를 위임하는 방식.
PROS
- element의 공통 조상에만 핸들러를 달면 하위 element들에도 적용할 수 있다. → 메모리 절약
- ex) 테이블의 경우
<table>
에 핸들러를 달고,e.target
으로 구별 후 작업
- ex) 테이블의 경우
- element가 추가 되어도 부모가 핸들링 하기 때문에 각각 리스너를 부여할 필요가 없다. → 코드가 짧아진다.
CONS
- 이벤트가 반드시 버블링 되어야 한다.
버블링 해결
-
그래서 버블링을 해결하기 위해 어떻게 해야할까? 몇 가지 방법이 있다.
###
event.preventDefault();
- 브라우저 동작은 막아주지만 (href 같은 것) 이벤트가 DOM에서 bubbling 되는 건 막지 못한다.
###
event.stopPropagation();
- 이벤트가 DOM에서 bubbling 되는 건 막지만, 브라우저 동작은 막지 못한다.
###
return false;
- JQuery 코드에서 많이 쓰이고, 브라우저 동작과 이벤트 버블링을 막고 어떤 콜백에서든 즉시 return한다.
const handleErrorBtnClicked = (e) =>{
e.stopPropagation();
if(retryCnt >= 3) {
setError(true)
return;
}
setRetryCnt(retryCnt+1);
refetch();
}
- bubbling되어서 부모의 onclick에 접근하였기 때문에, 버블링을 막기 위해
event.stopPropagation()
을 리스너 상단에 추가 해 주었다.
이제 retry 버튼을 클릭 하여도 부모 이벤트가 실행되지 않는다!
It works! :)
참고
How to correctly use preventDefault(), stopPropagation(), or return false; on events