✔️ Event Bubbling에 대하여

Wiiiiiii·2022년 10월 26일
0

Reactstudy

목록 보기
4/5
post-thumbnail

우리가 모달 기능을 구현하려고 할 때 어떤 식으로 코드를 작성할까?
div 태그를 먼저 만든 후 클릭 이벤트를 지정할 임의의 태그 (h4 혹은 버튼 등) 에 이벤트를 등록해주어야 한다

그런데 이때 이벤트가 지정된 태그 내에 또 다른 이벤트 혹은 함수를 지정한 버튼이나 태그가 있다고 가정할 때, 이 가장 안에 있는 태그를 클릭했을 때 총 몇번의 클릭을 수행한 것일까?

이벤트 버블링이란?

특정 화면 요소에서 이벤트가 발생했을 때 해당 이벤트가 더 상위의 요소들로 전달되어가는 특성을 의미한다

상위의 요소란?
HTML은 기본적으로 트리의 구조를 가진다, 여기서는 트리 구조상으로 한 단계 위의 요소를 상위요소라고 하며 body 태그를 최상위 요소라고 부른다

위의 코드는 3개의 계층적 HTML 태그에 각각 클릭이벤트를 설정하여 클릭 시 클래스 이름을 콘솔에 출력하는 콜백함수를 지정해 주었다

이 상태에서 최하위 요소인 <div class="three"> 를 클릭했을 때의 결과는 아래와 같다

div 태그 한개를 클릭했을 때 이벤트가 3개가 일어나는 이유는 브라우저가 이벤트를 감지하는 방식 때문이다

브라우저는 특정 화면 요소에서 이벤트가 발생했을 경우 그 이벤트를 최상위에 있는 화면 요소까지 이벤트를 전파시킨다

만약 이벤트 버블링과 같은 복잡한 구성을 원하지 않고 하나의 화면 요소에만 신경쓰고 싶다면 아래와 같은 코드를 작성해주면 된다

// javascript case

function nobubEvent (eventVal){
	eventVal.stopPropagation();
}

// React case

<button onClick={(eventVal) => {eventVal.stopPropagation();}}></button>

이벤트 캡쳐란?

이벤트 캡쳐는 이벤트 버블링과 반대 방향으로 진행되는 이벤트 전파 방식이다

위 그림처럼 특정 이벤트가 발생했을 때 최상위 요소인 body 태그에서 해당 태그를 찾아 내려간다

그렇다면 이벤트 캡쳐는 코드로 어떻게 구현할 수 있을까?

addEventListener() API 에서 옵션 객체에 capture:true 를 설정해주면 된다
그러면 해당 이벤트를 감지하기 위해 이벤트 버블링과 반대 방향으로 탐색한다

따라서, 아까와 동일하게 <div class="three"> 를 클릭해도 아래와 같은 결과가 나타난다

event.stopPropagation( )

이렇게 복잡한 이벤트 전달 방식을 알고 싶지 않고, 그냥 원하는 화면 요소의 이벤트만 신경 쓰고 싶다면 stopPropagation( ) 웹 API를 이용하면 된다

위 API는 해당 이벤트가 전파되는 것을 막는다 따라서, 이벤트 버블링의 경우에는 클릭한 요소의
이벤트만 발생시키고 상위 요소로 이벤트를 전달하는 것을 방해한다
그리고 이벤트 캡쳐의 경우에는 클릭한 요소의 최상위 요소의 이벤트만 동작시키고 하위 요소들로
이벤트를 전달하지 않는다

위와 같이 logEvent 함수에 stopPropagation( ) API를 사용한다면 앞의 '이벤트 버블링 예시'와 '이벤트 캡쳐 예시'에서 사용한 코드 기준으로 각각 three와 one 만이 출력될 것이다

이벤트 위임 (Event Delegation)

앞에서 살펴본 이벤트 버블링과 캡쳐는 사실 이벤트 위임을 위한 선수지식이라 해도 무방하다
이벤트 위임은 실제 바닐라 JS 로 웹 앱을 구현할 때 자주 사용하게 되는 코딩 패턴이다

즉 "하위 요소에 각각 이벤트를 붙이지 않고 상위 요소에서 하위 요소의 이벤트들을 제어하는 방식"이다

위 코드는 querySelectorAll() 을 이용해 화면에 존재하는 모든 인풋 박스 요소를 가져온 다음 각 인풋 박스의 요소에 클릭 이벤트 리스너를 추가한다

하지만 여기에 리스트 아이템을 추가하게 되면 정상적으로 동작하지 않게 된다

새로 추가된 리스트 아이템에 클릭 이벤트 리스너가 동작하지 않는 이유는 인풋 박스에 클릭 이벤트 리스너를 추가하는 시점에서 리스트 아이템은 2개이다

따라서, 새롭게 추가된 리스트 아이템에는 클릭 이벤트 리스너가 등록되지 않은 것이다

매번 이벤트 리스너를 달아주는 작업 자체가 매우 번거로우므로 이벤트 위임 (Event Delegation)을 사용한다

화면의 모든 인풋 박스에 일일이 이벤트 리스너를 추가하는 대신 이제는 인풋 박스의 상위 요소인 ul 태그, .itemList 에 이벤트 리스너를 달아놓고 하위에서 발생한 클릭 이벤트를 감지한다

이 부분이 앞에서 배웠던 이벤트 버블링이다

참고 |

https://joshua1988.github.io/web-development/javascript/event-propagation-delegation/#eventstoppropagation

profile
리액트를 주로 연구중입니다! FE Junior

0개의 댓글