Search

37장 Event

대분류
언어
서적
소분류
JS DeepDive
태그
이벤트
이벤트 핸들러
DOM
this
최종 편집 일시
2024/10/27 15:38
생성 일시
2024/02/08 00:19
14 more properties

이벤트

이벤트 드리블(Event-driven) 프로그래밍

이벤트 핸들러 : 특정 사건을 발생하여 이벤트를 발생 시키는데 이 경우 호출될 함수
이벤트가 발생했을 때 브라우저에게 이벤트 핸들러의 호출을 위임하는 것 --> 이벤트 핸들러 등록
이벤트 드리븐 프로그래밍 : 프로그램의 흐름을 이벤트 중심으로 제어하는 프로그래밍 방식

이벤트 타입

이벤트 타입은 이벤트의 종류를 나타내는 문자열

마우스 이벤트

이벤트 타입
이벤트 발생 시점
click
마우스 버튼을 클릭했을 때
dblclick
마우스 버튼을 더블 클릭했을 때
mousedown
마우스 버튼을 눌렀을 때
mouseup
누르고 있던 마우스 버튼을 놓았을 때
mousemove
마우스 커서를 움직였을 때
mouseenter
마우스 커서를 HTML 요소 안으로 이동했을 때 (버블링 X)
mouseover
마우스 커서를 HTML 요소 안으로 이동했을 때 (버블링 O)
mouseleave
마우스 커서를 HTML 요소 밖으로 이동했을 때 (버블링 X)
mouseout
마우스 커서를 HTML 요소 밖으로 이동했을 때 (버블링 O)

키보드 이벤트

이벤트 타입
이벤트 발생 시점
keydown
모든 키를 눌렀을 때
keypress
문자 키를 눌렀을 때 연속적으로 발생
keyup
누르고 있던 키를 놓았을 때 한 번만

포커스 이벤트

이벤트 타입
이벤트 발생 시점
focus
HTML 요소가 포커스를 받았을 때
blur
HTML 요소가 포커스를 잃었을 때
focusin
HTML 요소가 포커스를 받았을 때 (버블링)
focusout
HTML 요소가 포커스를 잃었을 때 (버블링)

폼 이벤트

이벤트 타입
이벤트 발생 시점
submit
form 요소 내의 submit 버튼을 클릭 시
reset
form 요소 내의 reset 버튼 클릭 시(최근 사용 X)
input
input, select, textarea 요소의 값이 입력 시
change
input, select, textarea 요소의 값이 변경되었을 시 --> 입력이 종료되어 값이 변경되면 이벤트 발생
readystatechange
HTML 문서의 로드와 파싱 상태를 나타내는 document.readyState 프로퍼티 값('loading', 'interactive', 'complete')이 변경될 때

값 변경 이벤트

이벤트 타입
이벤트 발생 시점
input
input, select, textarea 요소의 값이 입력 시
change
input, select, textarea 요소의 값이 변경되었을 시 --> 입력이 종료되어 값이 변경되면 이벤트 발생
readystatechange
HTML 문서의 로드와 파싱 상태를 나타내는 document.readyState 프로퍼티 값('loading', 'interactive', 'complete')이 변경될 때

DOM 뮤테이션 이벤트

이벤트 타입
이벤트 발생 시점
DOMContentLoaded
HTML 문서의 로드와 파싱이 완료되어 DOM 생성이 완료되었을 때

뷰 이벤트

이벤트 타입
이벤트 발생 시점
resize
브라우저 윈도우의 크기를 리사이즈할 때 연속적으로 발생한다.
scroll
웹페이지 또는 HTML 요소를 스크롤할 때 연속적으로 발생한다.

리소스 이벤트

이벤트 타입
이벤트 발생 시점
load
DOMContentLoaded 이벤트가 발생한 이후, 모든 리소스의 로딩이 완료되었을때(주로 window 객체에서 발생)
unload
리소스가 언로드될 때 (주로 새로운 웹페이지를 요청한 경우)
abort
리소스 로딩이 중단되었을 때
error
리소스 로딩이 실패했을 때

이벤트 핸들러

이벤트가 발생했을 때 실행될 함수

이벤트 핸들러 등록

등록 방법
1.
이벤트 핸들러 어트리뷰트 방식
2.
이벤트 핸들러 프로퍼티 방식
3.
addEventListener 메서드 방식

이벤트 핸들러 어트리뷰트 방식

<button onclick = "sayHi('honey')">Click me!</button> <script> function sayHi(name) { console.log(`Hi! ${name}.`); } </script>
HTML
복사
어트리뷰트 값으로 함수 참조가 아닌 함수 호출문 등의 문을 할당
이벤트 핸들러 어트리뷰트 값은 사실 암묵적으로 생성될 이벤트 핸들러의 함수 몸체를 의미
function onclick(event) { sayHi('honey'); }
TypeScript
복사
이벤트 핸들러 어트리뷰트 값으로 함수 참조를 할당해야 한다면 이벤트 핸들러에 인수 전달하기 어려움
이벤트 핸들러 어트리뷰트 방식은 HTML과 JS를 묶으므로 분리하는 면에서 사용하지 않는 것이 좋지만 CBD 방식의 프레임워크들은 이 방식으로 처리 (뷰를 구성하기 위한 구성 요소로 보기 때문)

이벤트 핸들러 프로퍼티 방식

const $button = document.querySelector('button'); $button.onclick = function() { console.log('button click'); };
TypeScript
복사
이벤트 핸들러 등록을 위해서 필요한 데이터
이벤트를 발생시킬 객체인 이벤트 타켓
이벤트 종류를 나타내는 문자열인 이벤트 타입
이벤트가 발생했을 때 실행될 함수인 이벤트 핸들러
js와 html을 분리할 순 있지만 프로퍼티에 하나의 이벤트 핸들러만 바인딩할 수 있다는 단점 존재

.addEventListener 메서드 방식

EventTarget.prototype.addEventListener('eventType', functionName [, useCapture]) 메서드 사용
EventTarget: 이벤트 타겟, eventType: 이벤트 타입, functionName: 함수 이름, useCapture true 인 경우 캡처링, false인 경우 버블링(기본값)
$button.addEventListener('click', function() { console.log('button click'); });
TypeScript
복사
이 메서드 방식은 이벤트 핸들러 프로퍼티에 바인딩 된 이벤트 핸들러에 아무런 영향을 주지 않고, 여러 개의 이벤트 핸들러를 등록할 수 있다. 이 경우, 등록된 순서대로 호출한다.
같은 이벤트를 중복 등록 시, 하나의 이벤트 핸들러만 등록됨.

이벤트 핸들러 제거

EventTarget.prototype.removeEventListener 메서드를 사용
처음 addEventListener의 3번째 인수는 false가 기본값이기 때문에 removeEventListener의 3번째 인수를 true로 주게 되면 모두 다 일치하지 않기 때문에 제거가 안됨. --> 모두 일치해야 이벤트 핸들러가 제거
무명함수 또한 참조할 수 없기 때문에 제거 불가능
addEventListener 함수 내에서 제거하기 위해 arguments.callee를 사용할 수 있지만, 코드 최적화와 거리가 멀어서 변수나 자료구조에 저장하여 제거하는 편이 좋다.
이벤트 핸들러 프로퍼티 방식으로 등록한 이벤트 핸들러는 이 removeEventListener로 제거할 수 없으며, 이벤트 핸들러 프로퍼티에 null을 할당

이벤트 객체

생성된 이벤트 객체는 이벤트 핸들러의 첫 번째 인수로 전달
이벤트 핸들러 어트리뷰트 방식의 경우 첫 번째 매개변수 이름이 반드시 event 여야 한다.

이벤트 객체의 상속 구조

이벤트 객체는 Object, Event 뿐만아니라 다양한 이벤트 관련 생성자 함수와 더불어 생성되는 프로토타입으로 구성된 프로토타입 체인의 일원이 된다.
이벤트 객체의 프로퍼티는 발생한 이벤트의 타입에 따라 달라진다.

이벤트 객체의 공통 프로퍼티

type, target(이벤트를 발생시킨 DOM요소), currentTarget(이벤트 핸들러가 바인딩된 DOM요소), eventPhase, bubbles, cancelable, defaultPrevented, isTrusted, timeStamp가 존재

마우스 정보 취득

마우스 포인터의 좌표 정보를 나타내는 프로퍼티: screenX/screenY, clientX/clientY, pageX/pageY, offsetX/offsetY
버튼 정보를 나타내는 프로퍼티: altKey, ctrlKey, shiftyKey, button
clientX/Y 는 뷰포트, 웹페이지의 가시 영역을 기준으로 마우스 포인터 좌표 표시

키보드 정보 취득

altKey, ctrlKey, shiftKey, metaKEy, key, keyCode 같은 고유의 프로퍼티를 소유

이벤트 전파

DOM 트리 상에 존재하는 DOM 요소 노드에서 발생한 이벤트가 DOM 트리를 통해 전파되는 것.
생성된 이벤트 객체는 이벤트를 발생시킨 DOM 요소인 이벤트 타깃을 중심으로 DOM 트리를 통해 전파된다.
캡처링 단계: 이벤트가 상위요소에서 하위 요소 방향으로 전파
타깃 단계: 이벤트가 이벤트 타깃에 도달
버블링 단계: 이벤트가 하위 요소에서 상위 요소 방향으로 전파
이벤트 핸들러 어트리뷰트/프로퍼티는 타깃 단계와 버블링 단계의 이벤트만 캐치 가능. 그러나 addEventListener 메서드 방식은 캡처링 단계의 이벤트도 선별적으로 캐치 가능(인수를 사용하여)
이벤트는 이벤트를 발생시킨 이벤트 타깃은 물론 상위 DOM 요소에서도 캐치 가능.
이벤트 패스(composedPath 메서드로 확인 가능하며 이벤트가 통과하는 DOM 트리 상의 경로를 의미)
버블링을 통해 전파되지 않는 것
포커스 이벤트: focus/blur
리소스 이벤트: laod/unload/abort/error
마우스 이벤트: mouseenter/mouseleave
-> 상위 요소에서 위 이벤트 캐치하려면 캡처링 단계의 이벤트를 캐치해야한다.

이벤트 위임

ul안의 모든 li 요소들이 클릭 이벤트에 반응하도록 이벤트 핸들러인 activate 함수를 등록해야 하는데 li의 개수가 많으면 모두 다 일일히 등록하기 힘드므로 상위 DOM 요소에 이벤트 핸들러를 등록 필요
-> ul 요소 노드에 onclick 프로퍼티에 이벤트 핸들러 등록으로 해결!
이러한 경우 이벤트 타깃 검사가 필요
function activate({target}) { if(!target.matches('#fruits > li')) return; }
TypeScript
복사

DOM 요소의 기본 동작 조작

DOM 요소의 기본 동작 중단

preventDefault() 메서드 사용
-> a나 checkbox, form 요소와 같이 이 요소들의 기본 동작을 중단하기 위해 사용

이벤트 전파 방지

stopPropagation() 메서드 사용
-> 하위 DOM 요소의 이벤트를 개별적으로 처리하기 위해 이벤트 전파 중단

이벤트 핸들러 내부의 this

이벤트 핸들러 어트리뷰트 방식

이벤트 핸들러 어트리뷰트 값으로 지정한 문자열은 이벤트 핸들러에 의해 일반 함수로 호출되므로 함수 내부 this는 전역 객체 지침
그러나 이벤트 핸들러를 호출할 때 인수로 전달한 this는 이벤트를 바인딩한 DOM 요소를 지침

이벤트 핸들러 프로퍼티 방식과 addEventListener 메서드 방식

프로퍼티 방식과 addEventListener 방식 모두 이벤트 핸들러 내부의 this는 이벤트를 바인딩한 DOM 요소를 가리킨다.
화살표 함수는 this 바인딩을 갖지 않아서 상위 스코프의 this를 가리킴
클래스의 경우 this는 인스턴스 바인딩이 아닌 이벤트 핸들러로 바인딩한 DOM 요소를 가리키기 때문에 bind 메서드를 사용하거나 클래스 필드에 할당한 화살표 함수를 이벤트 핸들러로 등록하여 이벤트 핸들러 내부의 this가 인스턴스를 가리키도록 한다.

이벤트 핸들러에 인수 전달

이벤트 핸들러 내부에서 함수를 호출하면서 인수 전달 가능
const checkUserNameLength = min => {...} $input.onblur = () => { checkUserNameLength(인수); }
TypeScript
복사
또는 이벤트 핸들러를 반환하는 함수를 만들어 호출하여 인수 전달
const checkUserNameLength = min => e => {...} $input.onblur = checkUserNameLength(인수);
TypeScript
복사

커스텀 이벤트

커스텀 이벤트 생성

커스텀 이벤트 : 개발자 의도로 생성된 이벤트
기존 이벤트 타입이 아닌 새로운 이벤트 타입도 가능한데 이 경우, CustomEvent 이벤트 생성자 함수 사용
이 생성된 커스텀 이벤트 객체는 버블링되지 않고 preventDefault 메서드로 취소할 수 없다. bubbles, cancelable 프로퍼티 값이 false로 기본 설정된다. 또한 istTrusted 프로퍼티 값도 언제나 false이다.
커스텀 이벤트 객체는 이벤트 타입에 따라 가지는 이벤트 고유의 프로퍼티 값을 지정할 수 있는데 두 번째 인수로 프로퍼티를 전달

커스텀 이벤트 디스패치

dispatchEvent 메서드로 디스패치(이벤트를 발생시키는 행위) 가능
dispatchEvent 메서드는 이벤트 핸들러를 동기 처리방식으로 호출하며, 기존 이벤트 타입이 아닌 임의의 이벤트 타입을 지정하여 커스텀 이벤트 객체를 생성한 경우 addEventListener 메서드 방식으로 이벤트 핸들러를 등록 후 디스패치 사용 가능