💡 이벤트 전파 (event propagation)
DOM 트리 상에 존재하는 DOM 요소 노드에서 발생한 이벤트는 DOM 트리를 통해 전파됨
<ul id="fruits">
<li>Apple</li>
<li>Banana</li>
<li>Orange</li>
</ul>
ul 요소의 두 번째 자식 요소인 li 요소를 클릭하면 클릭 이벤트가 발생함
이때, 생성된 이벤트 객체는 이벤트를 발생시킨 DOM 요소인 이벤트 타깃(event target)을 중심으로 DOM 트리를 통해 전파됨
이미지 출처 | https://poiemaweb.com/js-dom
이벤트는 이벤트를 발생시킨 이벤트 타깃은 물론 상위 DOM 요소에서도 캐치할 수 있음
💡 다음 이벤트는 버블링을 통해 전파되지 않음
- 포커스 이벤트 : focus/blur
- 리소스 이벤트 : load/unload/abort/error
- 마우스 이벤트 : mouseenter/mouseleave
반드시 위 이벤트를 상위 요소에서 캐치해야 한다면 대체 이벤트 (버블링을 통해 전파)
- 포커스 이벤트 : focusin/focusout
- 마우스 이벤트 : mouseover/mouseout
💡 이벤트 위임 (event delegation)
여러 개의 하위 DOM 요소에 각각 이벤트 핸들러를 등록하는 대신 하나의 상위 DOM 요소에 이벤트 핸들러를 등록하는 방법
이벤트 위임을 통해 하위 DOM 요소에 발생한 이벤트를 처리할 떄 주의할 점은 상위 요소에 이벤트 핸들러를 등록하기 때문에
이벤트 타깃, 실제로 발생시킨 DOM 요소가 개발자가 기대한 DOM 요소가 아닐 수 있음
-> 이벤트에 필요한 DOM요소에 한정하여 이벤트 핸들러가 실행되도록 이벤트 타깃 검사 필수
<div class="container">
<button class="btn1">Button1</button>
<button class="btn2">Button2</button>
</div>
<script>
// 이벤트 위임. 클릭된 하위 버튼 요소의 color를 변경
documnet.querySelector('.container').onclick = ({}) => {
if (!target.matches('.container > button')) return;
target.style.color = 'red;
};
// .btn2 요소는 이벤트를 전파하지 않으므로 상위 요소에서 이벤트를 캐치
// 자신이 발생시킨 이벤트가 전파되는 것을 중단하여 자신에게 바인딩된 이벤트 핸들러만 실행됨
documnet.querySelector('.btn2').onclick = ({}) => {
e.stopPropagation(); // 이벤트 전파 중단
e.target.style.color = 'blue;
};
</script>
<button onclick="handleClick(this)">Click me</button>
<script>
function handleClick(button) {
console.log(button); // 이벤트를 바인딩한 button 요소
console.log(this); // window
}
</script>
<button class="btn">Button</button>
<script>
const $btn = document.querySelector('.btn');
$btn.onclick = e => {
// 화살표 함수 내부의 this는 상위 스코프의 this를 가르킴
console.log(this); // window
console.log(e.currentTarget); // $btn
console.log(this === e.currentTarget); // true
// this는 window를 가르키므로 window.textContnet에 NaN(undefined + 1)을 할당
++this.textContent;
};
</script>