한 요소에 이벤트가 발생하면, 이 요소에 할당된 핸들러가 동작하고, 이어서 부모 요소의 핸들러가 동작한다.
가장 최상단의 조상 요소를 만날 때까지 이 과정이 반복되면서 요소 각각에 할당된 핸들러가 동작하는게 이벤트 버블링
즉 방울처럼 => 하나의 요소에 이벤트가 발생하면 최상단의 요소를 만날때까지 상위로 이벤트가 전달되는 현상.
다음과 같은 코드에서 가장 안쪽의 p태그를 클릭한다면? => p → div → form 순서로 3개의 얼럿 창이 생성됨
- p에 할당된 onclick 핸들러가 동작합니다.
- 바깥의 div에 할당된 핸들러가 동작합니다.
- 그 바깥의 form에 할당된 핸들러가 동작합니다.
- document 객체를 만날 때까지, 각 요소에 할당된 onclick 핸들러가 동작합니다.
자식 요소에서 발생한 이벤트가 부모 요소부터 시작하여 이벤트를 발생시킨 자식 요소까지 도달하는 것을 캡처링이라 한다. 즉 이벤트가 하위요소로 전파되는 단계임.
이벤트 버블링과 캡쳐링은 둘 중에 하나만 발생하는 것이 아니라, 캡쳐링으로부터 시작해서 버블링으로 종료됨.
td를 클릭하면 이벤트가 최상위 조상에서 시작해 아래로 전파되고(캡처링 단계), 이벤트가 타깃 요소에 도착해 실행된 후(타깃 단계), 다시 위로 전파됩니다(버블링 단계). 이런 과정을 통해 요소에 할당된 이벤트 핸들러가 호출됩니다.
addEventListener 메소드의 세번째 매개변수에 true를 설정하면 캡처링으로 전파되는 이벤트를 캐치하고 false 또는 미설정하면 버블링으로 전파되는 이벤트를 캐치한다. (캡처링시 동작여부 결정)
li태그에 이벤트를 등록하려고 할 때 만일 이벤트 전파 개념이 없다면, li 요소 마다 일일히 이벤트를 등록해야 할 것이다.
버블링의 특성을 통해 우리는 그 부모 요소인 ul 요소에만 이벤트를 등록하면, 어떤 몇번째의 li 요소를 클릭하든 부모 요소로 이벤트가 전파되기 때문에 불필요한 코드작성을 줄일 수 있다.
이 기법을 이벤트 위임이라 부른다.
아래의 코드에서 item이 1억개라면? React는 1억개에 아이템에 대한 이벤트 리스너를 모두 등록하는걸까?
결론부터 말하지면 아니다. React에서는 이벤트를 내부적으로 이벤트 위임 방식으로 처리한다.
React 17버전부터는 이벤트핸들러를 Document Level이 아닌 React 트리가 렌더되는 root Dom container에 부착함 (아래는 next.js라서 "__next"가 root Container이다)
React에서는 크로스브라우징 문제를 해결하기 위해 브라우저에서 발생하는 native Event를 그대로 사용하는 것이 아니라 SyntheticEvent 객체를 이용해 Native Event를 감싸는 방식을 사용함. => 가상돔생성시점에 발생
실제 코드레벨에서 onClick와 같은 이벤트 핸들러에서 바로 이벤트가 처리되는게 아님. => dispatchEvent라는 함수를 통해 Root Node로 전달됨. => Root node에서 target Dom node를 찾아 이벤트가 실행됨.
Root Node에서는 React Dom Tree가 생성될 때 Native Event와 SyntheticEvent를 매핑하는 과정이 존재함.
React 이벤트 핸들링과정 : https://handhand.tistory.com/287
React Deep Dive – 이벤트를 핸들링하는 법 : https://inpa.tistory.com/entry/JS-%F0%9F%93%9A-%EB%B2%84%EB%B8%94%EB%A7%81-%EC%BA%A1%EC%B3%90%EB%A7%81
createRoot함수 => listenToAllSupportedEvents 호출 => Native Event와 Synthetic 이벤트를 매핑함.
네트워크탭에서 Elements Tab에 Event Listner라는 항목이 존재한다.
이런식으로 Framework listeners 항목을 체크했을때, 프레임워크에 등록된 이벤트 리스너들만을 모아서 볼 수 있다.
ref)
✔ PoimeaWeb Event : https://poiemaweb.com/js-event
✔ 한눈에 이해하는 이벤트 흐름제어(blog) : https://inpa.tistory.com/entry/JS-%F0%9F%93%9A-%EB%B2%84%EB%B8%94%EB%A7%81-%EC%BA%A1%EC%B3%90%EB%A7%81
✔ JavaScript Info 버블링과 캡쳐링 : https://ko.javascript.info/bubbling-and-capturing
✔ React SyntheticEvent(공식문서) : https://ko.legacy.reactjs.org/docs/events.html#gatsby-focus-wrapper