이벤트 등록은 아래처럼 addEventListner()
메서드를 이용해서 가능하다.
EventTarget.addEventListener(type, handler, [options])
type: 이벤트의 유형
handler: 이벤트가 발생하면 실행될 콜백, 이벤트가 발생한 정보를 알리는 Event
객체만을 유일한 인자로 가진다.
options: 이벤트의 특징을 정하는 객체, 아래의 프로퍼티를 가진다.
capture: 어느 단계에서 이벤트를 캐치할지 정하는 프로퍼티. true
는 캡처링, false
는 버블링이다.
once: true
일 경우 이벤트가 트리거 되면 자동으로 리스너가 삭제된다.
passive: true
일 경우 핸들러로 지정한 콜백에서 절대로 preventDefault()
메서드를 호출하지 않을 것을 알린다.
options
는 객체 대신 boolean
형태도 가능한데, 이런 경우 capture
의 값을 변경하는 것과 같다.캡처링(Capturing)
이벤트가 최상위 요소부터 시작하여 타깃 요소까지 아래로 전파되는 방식
capture
프로퍼티가 true
면 캡처링 방식으로 동작한다.
버블링(Bubbling)
이벤트가 타깃 요소부터 시작하여 최상위 요소까지 위로 전파되는 방식
capture
프로퍼티가 false
혹은 3번째 인수가 없을 경우 버블링 방식으로 동작한다.
이벤트의 전파는 하나만 일어나는 것이 아니라 캡처링부터 시작하여 버블링으로 종료되고, 단지 capture
프로퍼티를 통해 어느 단계에서 리스너가 실행될 지 정하는 것이다.
stopPropagation()
메서드를 이용해 전파를 중단할 수 있다.
이벤트가 전파되는 특성을 이용해서, 상위 요소에서 하위 요소들의 이벤트를 관리하는 방식
각 요소마다 반복되는 이벤트를 추가하는 번거로움을 줄여주며, 코드도 훨씬 간결해진다.
동적으로 추가된 요소에 대해서도 이벤트 처리가 가능하다.
브라우저에서 기본적으로 제공하는 이벤트가 아닌, 직접 생성한 이벤트
Event
생성자를 이용해서 새로운 이벤트를 생성한다.
const event = new Event(type[, option])
type: 이벤트 타입을 나타낸다.type
은 브라우저에서 제공하는 내장 이벤트가 될 수도, my-event
같은 커스텀 이벤트가 될 수도 있다.
option: 이벤트의 특징을 정의한 객체
bubbles: boolean
타입, true
인 경우 이벤트가 버블링 된다.
cancelable: boolean
타입, true
인 경우 이벤트의 기본 동작을 차단(event.preventDefault()
)함을 알린다.
bubbles
와 cancelable
모두 false
가 기본값이며, 2번째 인수가 없다면 두 프로퍼티 모두 기본값으로 처리된다.
위에서 사용한 Event()
생성자 말고도 CustomEvent()
생성자를 이용해서도 이벤트 생성이 가능하다.
const event = new CustomEvent(type[, option])
기존의 Event()
생성자와 다른 점은 option
에서 객체 형태의 detail
프로퍼티를 이용해 정보를 이벤트에 전달할 수 있으며, 읽는 사람으로 하여금 명시적으로 커스텀 이벤트라는 것을 알릴 수 있다.
이벤트의 실행은 EventTarget.dispatchEvent()
메서드를 이용해서 실행한다.
EventTarget.dispatchEvent(event)
dispatchEvent()
메서드를 이용해서 버튼을 클릭하지 않고도 click
이벤트를 트리거 하는 예제를 보자.
<html>
<body>
<button type="button">Click?</button>
<script>
const $button = document.querySelector('button');
$button.addEventListener('click', e => {
console.log('Clicked!');
});
const event = new CustomEvent('click');
setTimeout(() => {
$button.dispatchEvent(event);
}, 1000);
</script>
</body>
</html>
버튼을 클릭하지 않아도 1초(1000ms) 뒤에 자동으로 click
이벤트가 발생한다.
내장 이벤트가 아닌, 임의의 이벤트 이름으로 변경해도 정상적으로 동작한다.
<html>
<body>
<button type="button">Click?</button>
<script>
const $button = document.querySelector('button');
$button.addEventListener('autoClick', e => {
console.log('Clicked!');
});
const event = new CustomEvent('autoClick');
setTimeout(() => {
$button.dispatchEvent(event);
}, 1000);
</script>
</body>
</html>
마지막으로 호출된 함수가 일정 시간이 지나기 전까지 다시 호출되지 않도록 하는 기법
주로 성능을 향상시키기 위해 사용한다.
const $input = document.querySelector('input');
let timer = null;
$input.addEventListener('input', e => {
const { value } = e.target;
if (!timer) {
timer = setTimeout(() => {
console.log(value);
timer = null;
}, 500);
}
});
여러 차례 호출 된 함수들 중, 마지막 함수만 호출하는 기법
주로 API와의 통신 횟수를 줄이려 할 때 사용한다.
const $input = document.querySelector('input');
let timer = null;
$input.addEventListener('input', e => {
const { value } = e.target;
if (timer) {
clearTimeout(timer);
}
timer = setTimeout(() => {
console.log(value);
}, 500);
});
이벤트 발생
서버로 정보 변경 요청
요청에 대한 서버 응답
응답을 기반으로 상태 변경 및 렌더링
이벤트 발생
서버에게 전달할 요청이 성공적으로 처리되었다고 확신, 미리 상태 변경 및 렌더링
서버로 정보 변경 요청
요청 실패 시 이전 상태로 되돌림
참고 자료
Event | PoiemaWeb
EventTarget.addEventListener() | MDN
Event() - Web API | MDN
브라우저 이벤트 소개 | 모던 JS 튜토리얼
커스텀 이벤트 디스패치 | 모던 JS 튜토리얼
쓰로틀링과 디바운싱 | Zerocho
Optimistic and Pessimistic UI Rendering Approaches | Medium