7. 이벤트
1. 이벤트 객체
이벤트 발생 시 이벤트 객체가 생성된다.
생성된 이벤트 객체는 이벤트 핸들러의 첫 번째 인수로 전달된다.
이는 브라우저가 이벤트 핸들러를 호출할 때 이벤트 객체를 인수로 전달하기 때문에, 전달받을 매개변수를 명시적으로 선언해야 하기 때문이다.
이벤트가 발생하면 암묵적으로 생성되는 이벤트 객체 또한 생성자 함수에 의해 생성된다.
이는 프로토타입 체인의 일원이 된다.
Event.prototype에 정의된 이벤트 프로퍼티는 모든 파생 객체에 상속된다.
공통 프로퍼티 | 설명 | 타입 |
type | 이벤트 타입 | string |
target | 이벤트를 발생시킨 DOM 요소 | DOM 요소 노드 |
currentTarget | 이벤트 핸들러가 바인딩된 DOM 요소 | DOM 요소 노드 |
eventPhase | 이벤트 전파 단계 0: 이벤트 없음, 1: 캡처링, 2: 타깃, 3: 버블링 |
number |
bubbles | 이벤트를 버블링으로 전파하는지 여부, 아래 이벤트는 bubbles: false로 버블링 하지 않는다. 포커스 이벤트: focus/blur 리소스 이벤트: load/unload/abort/error 마우스 이벤트: mouseenter/mouseleave |
boolean |
cancelable | preventDefault 메서드로 이벤트의 기본 동작을 취소할 수 있는지 여부, 다음 이벤트는 cancelable: false로 취소 블가. 포커스 이벤트: focus/blur 리소스 이벤트: load/unload/abort/error 마우스 이벤트: dbclick/mouseenter/mouseleave |
boolean |
defaultPrevented | preventDefault 메서드로 이벤트를 취소했는지 여부 | boolean |
isTrusted | 사용자 행위로 발생한 이벤트인지 여부 | boolean |
timeStamp | 이벤트가 발생 시각(1970/01/01/00:00:0부터 경과한 밀리초) | number |
2. 이벤트 전파
DOM 트리 상에 존재하는 DOM 요소 노드에서 발생한 이벤트는 DOM 트리를 통해 전파된다.
이를 이벤트 전파(Event propagation)라고 한다.
<ul id='fruits'>
<li>apple</li>
<li>banana</li>
<li>orange</li>
</ul>
li 요소를 클릭하면 클릭 이벤트가 발생하고, 이때 생성된 이벤트 객체는 이벤트를 발생시킨 DOM 요소인 이벤트 타깃을 중심으로 DOM 트리를 통해 전파된다.
- 캡처링 단계: 이벤트가 상위에서 하위 요소로 전파
- 타깃 단계: 이벤트가 타깃에 도달
- 버블링 단계: 이벤트가 하위 요소에서 상위 요소 방향으로 전파
이처럼 이벤트는 이벤트를 발생시킨 타깃은 물론 상위 DOM 요소에서도 캐치할 수 있다.
DOM 트리를 통해 전파되는 이벤트는 이벤트 경로(Event.prototype.composedPath)에 위치한 모든 DOM 요소에서 캐치 가능하다.
3. 이벤트 위임
이벤트 위임(event delegation)은 여러 하위 DOM 요소에 개별적으로 이벤트 핸들러를 등록하지 않고, 하나의 상위 DOM 요소에 등록하는 방법이다.
다만 주의할 점은 이벤트를 일으킨 타겟이 개발자가 기대한 DOM 요소가 아닐 수 있다는 것이다.
이것을 고려해서 이벤트 타겟을 검사할 필요가 있다.
4. DOM 요소의 기본 동작 조작
이벤트 객체의 preventDefault 메서드는 이러한 DOM 요소의 기본 동작을 중단시킨다.
document.querySelector('a').onclick = e => {
e.preventDefault(); // a 태그의 기본 동작 중단
};
document.querySelector('input[type=checkbox]').onclick = e => {
e.preventDefault(); // checkbox의 기본 동작 중단
};
이벤트 객체의 stopPropagation 메서드는 이벤트 전파를 중지시킨다.
<div class="container">
<button class="btn1">Button 1</button>
<button class="btn2">Button 2</button>
<button class="btn3">Button 3</button>
</div>
<script>
// 이벤트 위임, 클릭된 하위 버튼 요소의 color를 변경한다.
document.querySelector('.container').onclick = ({ target }) => {
if (!target.matches('.container > button')) return;
target.style.color = 'red';
};
// .btn2 요소는 이벤트를 전파하지 않는다. 상위 요소에서 이벤트 캐치가 불가능하다.
document.querySelector('.btn2').onclick = e => {
e.stopPropagation();
e.target.style.color = 'blue';
};
</script>