[ 이벤트 종류 ]
마우스 이벤트 : click, mouseover, mouseout, mouseup
키보드 이벤트 : keydown, keyup, keypress
폼 이벤트 : submit, change, focus, blur
문서 이벤트 : load, resize, scroll
[ DOM 이벤트 전파 (Event Propagation) 단계 ]
캡처링 → 타깃 → 버블링
1. 캡처링 단계 (Capturing Phase)
** 기본적으로는 캡처링 이벤트 리스너를 설정하지 않으면 무시되는 단계
- 이벤트가 최상위 요소(window)에서 시작해 이벤트 대상 요소까지 내려가는 과정입니다.
- 클릭 이벤트가 발생했을 때 브라우저는 최상위 부모 요소인 window에서부터 차례대로 각 부모 요소를 거쳐 이벤트가 발생한 타깃 요소(실제 클릭된 요소)로 내려갑니다.
2. 타깃 단계 (Target Phase)
- 이벤트가 실제로 발생한 요소에서 실행되는 단계입니다.
- 이 단계에서 이벤트 핸들러가 실행되며, 이벤트 핸들러가 타깃 요소에 직접적으로 바인딩되어 있다면 이 시점에 동작합니다.
3. 버블링 단계 (Bubbling Phase)
- 이벤트가 타깃 요소에서 시작해 부모 요소를 거슬러 올라가면서 전파되는 과정입니다.
- 버블링 단계에서는 이벤트가 다시 부모 요소로 전파되며, 상위 요소들에 바인딩된 이벤트 핸들러들이 실행됩니다.
- 최종적으로 document와 window까지 도달합니다.
# 이벤트 버블링 (event bubbling)
: DOM에서 발생한 이벤트가 하위 요소에서 상위 요소 방향으로 전파되는 과정 (버블은 밑에서 위로)
- 특정 화면 요소에서 이벤트가 발생했을 때 해당 이벤트가 그 요소의 부모 요소로 전파되며 최상위 요소(document 또는 window)까지 전달되는 현상
- 이벤트 위임을 가능하게 하는 중요한 메커니즘
# 이벤트 위임 (event delegation)
: 버블링을 활용해서 상위 요소에 이벤트 리스너를 단 한번만 할당하여 하위 요소들의 이벤트를 처리하는 것
- 한 개의 부모 요소에 이벤트 리스너를 할당하여, 그 부모 요소의 자식 요소들에서 발생하는 이벤트를 처리하는 방식
- 이벤트의 중복이 감소하여 관리가 쉬워지고, 메모리 사용을 줄이며, 자식 요소가 동적으로 추가되거나 변경될 때도 유연하게 대응
사용 예시 )
- event.target.id 를 이용하여 실제로 클릭된 요소를 참조해서 이벤트가 실제 클릭된 요소와 일치할 때만 알럿 노출
- 최상위 코드에만 event listener 를 달아주고, event.target.id로 분기처리하면 이벤트 리스너를 한번만 선언하면 된다.
if(event.target.id === 'btn') alert('btn clicked');
# 이벤트 캡처링 (event capturing)
- 이벤트 버블링과는 반대로 최상위 요소에서 시작하여 발생한 요소로 이벤트가 전파되는 과정
- 이벤트가 상위 요소에서 하위 요소 방향으로 전파
- 기본적으로 브라우저는 캡처링 단계에서 이벤트 핸들러를 실행하지 않는다.
- 특정 부모 요소에서 이벤트를 우선 처리하고 싶은 경우 캡처링 단계에서 이벤트를 가로채면 버블링 단계로 이벤트가 전달되기 전에 처리할 수 있다.
- React에서는 onClickCapture 속성을 사용하여 캡처링 단계를 설정한다.
- 불필요한 경우가 많고 복잡성이 증가하기 때문에 잘 사용하지 않는다.
캡처링의 명시적 사용 예시 )
- addEventListener 함수의 세 번째 인자로 { capture: true }를 설정함으로써 이벤트 캡처링을 활성화
- 3번째 인자는 false 가 기본값임.
document.getElementById('div1').addEventListener('click',function(){
alert('div 1 clicked')
}, { capture: true }); // 이벤트 캡처링으로 상위요소에서 이벤트를 낚아챔(캡처함)
document.getElementById('btn').addEventListener('click',function(){
alert('btn clicked')
}); // 하위요소 이벤트는 동작하지 않음
[ 이벤트 버블링 방지 방법 ]
# event.stopPropagation()
: 이벤트 전파(버블링 및 캡처링)를 중지하는 메서드
- DOM 이벤트가 부모요소, 자식 요소로 전파되는 것을 원하지 않는 경우 사용
- 하위 요소에서 이벤트 발생시 상위 요소의 이벤트 리스너가 실행되지 않게 (버블링의 중단) 하고 싶을 때
- preventDefault 처럼 이벤트의 기본 동작을 중단하지는 않음
사용 예시)
- onClick={(e) => e.stopPropagation()}
document.getElementById('btn').addEventListener('click', function(event){
alert('btn clicked');
event.stopPropagation();
}
- 모달 바깥을 클릭하면 모달이 닫히고, 모달 내부를 클릭하면 닫히지 않도록 구현할 때 사용할 수 있음
# event.preventDefault()
: 이벤트의 기본 동작 방지 메서드
- 웹 브라우저는 많은 HTML 요소들에 대해 기본적인 동작을 가지고 있는데, 이 메서드를 사용하면 이러한 기본 동작을 취소한다.
- 이벤트의 전파를 중단하지는 않음
- 사용자가 기대하는 기본 동작을 변경하거나 새로운 동작을 추가할 때 유용하다.
사용 예시 )
- submit 태그를 누르면 기본 동작으로 새로고침이 되는데 새로고침 방지
document.querySelector('form').addEventListener('submit', function(event){
event.preventDefault();
});
- 그 외에도 폼 제출 방지, 링크 클릭 방지, 마우스 오른쪽 클릭 방지 등에 사용한다.
# 내가 겪은 이벤트 버블링 문제
문제 : 리스트 테이블 특정 행을 클릭하면 페이지를 이동하는 동작이 걸려있는데 그 행에 있는 select box를 눌러도 selectbox option이 뜨지않고 페이지 이동 동작이 실행되는 문제
[ 원인 ]
이벤트 버블링
1. <tr>에 onClick 이벤트가 등록되어 있어서 행을 클릭하면 상세 페이지로 이동하도록 설정되어 있음.
2. 하지만 <select>를 클릭햇을 때 발생한 '클릭 이벤트'가 부모 요소인 <tr>까지 전파(버블링)되어 <tr>의 클릭이벤트가 실행됨.
3. 이 때문에 <select>를 클릭했음에도 옵션이 열리기 전에 상세 페이지로 이동하는 문제가 발생함.
=> 즉, 이벤트는 <select>(하위)에서 먼저 발생했고, onClick이 <tr>(상위)까지 버블링되어 navigate()가 실행된 것.
[ 해결 방법 ]
이벤트 버블링 방지
: <select> 클릭 시 event.stopPropagation()을 사용하면 이벤트가 <tr>로 전파되지 않도록 차단할 수 있다.
'Javascript' 카테고리의 다른 글
[JS] 스코프, 실행 컨텍스트, 클로저 ♦︎ (1) | 2024.09.25 |
---|---|
[JS] BOM, window 객체 사용하기 ♦︎ (0) | 2024.08.02 |
[JS] Javascript 문법적 특징 (1) | 2024.07.01 |
Javascript 기초문법 - class (2) | 2024.06.28 |
[JS] Prototype (1) | 2024.05.26 |