1 분 소요

Created By: 성희 배 Last Edited: Apr 24, 2020 6:58 PM Tags: cs

before-min

호텔 클로닝 사이드 프로젝트에서 발생한 문제이다.

자식 버튼을 누를 시에 부모의 이벤트가 호출되는 현상이 나타났다. 문제는 이벤트 버블링 때문이었다.


이벤트 버블링

  • 하위 엘리먼트에 이벤트 발생 시 그 엘리먼트부터 상위 요소까지 이벤트가 전달되는 방식

Untitled

  • 위와 같은 형식이 있을 때, li 를 클릭하게 되면 liuldiv 순으로 호출된다.

이벤트 캡쳐링

  • 하위 엘리먼트에 이벤트 핸들러가 있을 때 상위 엘리먼트부터 이벤트가 발생 해 하위 엘리먼트까지 이벤트가 전달됨

Untitled 1

  • 똑같은 형식에 li를 클릭 시 ul을 호출하고 싶을때, ul의 이벤트 리스너에 {capture : true}로 우선순위를 부여할 수 있다.

이벤트 위임 (참고)

조상에 이벤트를 등록하여 조상이 하위 element에 이벤트를 위임하는 방식.

PROS

  • element의 공통 조상에만 핸들러를 달면 하위 element들에도 적용할 수 있다. → 메모리 절약
    • ex) 테이블의 경우 <table>에 핸들러를 달고, e.target으로 구별 후 작업
  • 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()을 리스너 상단에 추가 해 주었다.

after-min

이제 retry 버튼을 클릭 하여도 부모 이벤트가 실행되지 않는다!

It works! :)

참고
How to correctly use preventDefault(), stopPropagation(), or return false; on events

카테고리:

업데이트: