JavaScript
20210719 JavaSciprt DeepDive 15 : 이벤트 Event
JavaScript Deep Dive 15
📄 용어 및 중요사항 정리
이벤트
브라우저는 특정 상황이 발생시 이를 감지하여 특정한 타입의 이벤트를 발생 시킴
이벤트 핸들러
: 이벤트 발생시 호출될 함수를 말함이벤트 핸들러 등록
: 이벤트 발생시 브라우저에게 이벤트 핸들러(함수)의 호출을 위임하는 것- 이벤트 핸들러 프로퍼티에 함수 할당하여 가능함
이벤트 드리븐 프로그래밍
: 프로그램의 흐름을 이벤트 중심으로 제어하는 프로그래밍 방식이벤트 타입
: 이벤트의 종류를 나타내는 문자열
이벤트 타입
이벤트 타입 | 이벤트 발생 시점 |
---|---|
마우스 이벤트 |
|
click | 마우스 버튼을 클릭했을 때 |
dblclick | 마우스 버튼을 더블 클릭했을 때 |
mousedown | 마우스 버튼을 눌렀을 때 |
mouseup | 누르고 있던 마우스 버튼을 놓았을 때 |
mousemove | 마우스 커서를 움직였을 때 |
mouseenter | 마우스 커서를 HTML 요소 안으로 이동했을 때(이벤트 버블링 X) |
mouseover | 마우스 커서를 HTML 요소 안으로 이동했을 때(이벤트 버블링 O) |
mouseleave | 마우스 커서를 HTML 요소 밖으로 이동했을 때(이벤트 버블링 X) |
mouseout | 마우스 커서를 HTML 요소 밖으로 이동했을 때(이벤트 버블링 O) |
키보드 이벤트 |
|
keydown | 모든 키를 눌렀을 때 발생 ctrl, option, shift, tab, delete, 방향키 등-> 1번만 발생 문자, 숫자, 특수 문자, enter -> 연속적으로 발생 |
keypress | 문자 키를 눌렀을 때 연속적으로 발생 (문자, 숫자, 특수 문자, enter 만 발생), 폐지 되어 비추 |
keyup | 누르고 있던 키를 놓았을 때 한번만 발생(keydown과 마찬가지) |
포커스 이벤트 |
|
focus | HTML 요소가 포커스를 받았을 때(버블링X) |
blur | HTML 요소가 포커스를 잃었을 때(버블링X) |
focusin | HTML 요소가 포커스를 받았을 때(버블링O) |
focusout | HTML 요소가 포커스를 잃었을 때(버블링O) |
폼 이벤트 |
|
submit | form 요소 내의 submit 버튼을 클릭시 |
reset | form 요소 내의 reset 버튼을 클랙했을 때(최근엔 사용X) |
값 변경 이벤트 |
|
input | input, select, textarea 요소의 값이 입력되었을 때 |
change | input, select, textarea 요소의 값이 변경되었을 때 (사용자 입력시 input 이벤트 발생, 사용자 입력이 종료되어 값 변경시 change 이벤트 발생) |
readystatechange | HTML 문서의 로드와 파싱 상태를 나타내는 document,readyState 프로퍼티 값(loading, interactive, complete)이 변경 될때 |
DOM 뮤테이션 이벤트 |
|
DOMContentLoaded | HTML 문서의 로드와 파싱이 완료되어 DOM 생성이 완료되었을 때 |
뷰 이벤트 |
|
resize | 브라우저 윈도우의 크기를 리사이즈할 때 연속적으로 발생(window 객체에서만 발생) |
scroll | 웹페이지(document) 또는 HTML 요소를 스크롤할 떄 연속적으로 발생 |
리소스 이벤트 |
|
load | DOMContentLoaded 이벤트 발생한 이후, 모든 리소스의 로딩이 완료 되었을 떄 |
unload | 리소스가 언로드 될 때(새로운 웹페이지 요청시) |
abort | 리소스 로딩이 중단되었을 때 |
error | 리소스 로딩이 실패했을 때 |
이벤트 핸들러 등록
- 브라우저에게 이벤트 핸들러의 호출 위임하는 것
이벤트 핸들러 어트리뷰트 방식
이벤트 핸들러 어트리뷰트
: on 접두사 + 이벤트 타입- HTML 이벤트 핸들러 어트리뷰트에 함수 호출문 등의
여러 문
을 할당하면 이벤트 핸들러가 등록됨(주의!!! 함수 참조X, 함수 호출문) - 이벤트 핸들러 어트리트에 할당되는 값은 암묵적으로 생성될 이벤트 핸들러의 함수 몸체를 의미
CBD 방식
: Angular, React, Svelte, Vue.js 같은 프레임워크/라이브러리에서 이벤트 핸들럴 어트리뷰트 방식으로 이벤트 처리하는 것
이벤트 핸들러 프로퍼티 방식
- DOM 노드 객체(window객체, Document, HTMLElement 타입)의 경우 이벤트 핸들러 프로퍼티를 갖음
- DOM 노드 객체의 이벤트 핸들러 프로퍼티에 값을 할당(바인딩)하는 방식
이벤트 타깃(event target)
: 이벤트를 발생시킬 객체(노드 객체)이벤트 타입
: 이벤트의 종류를 나타내는 문자열이벤트 핸들러
: 이벤트에 발생시킬 함수
- HTML과 JS가 섞이는 것을 방지 할수 있음, 이벤트 핸들러 프로퍼티에 하나의 이벤트 핸들러만 가능함
- 최근에 할당된 값으로 됨 (덮어 씌워 짐)
- DOM 노드 객체(window객체, Document, HTMLElement 타입)의 경우 이벤트 핸들러 프로퍼티를 갖음
addEventListener 메서드 방식
EventTarget.prototype.addEventListener('eventType', eventHandler [, useCapture])
:- eventType : 이벤트 타입(종류) 문자열 (on 접두사가 붙지 않음)
- eventHandler : 이벤트 발생시 호출할 함수
- useCapture : true -> capturing 사용 / false -> bubbling(기본값)
- 이벤트 핸들러 프로퍼티 방식과 이벤트리스너 메서드 방식을 중복으로 사용하는 경우 둘다 실행 됨
- 이벤트 리스너 메서드 방식은 하나 이상의 이벤트 핸들러 등록 가능
- 이벤트 헨들러 이름이 중복되면 하나만 등록 됨
이벤트 핸들러 제거
이벤트 리스너 방식 제거
EventTartget.prototype.removeEventListener('eventType', eventHandler, [, useCapture])
- 등록한 event를 제거하려면, 등록 했을 떄 전달한 인수가 제거할때 사용하는 인수와 동일해야함
- 동일한 이벤트 핸들러 (무명 함수를 이벤트 핸들러로 등록한 경우 제거 불가함)
- 기명 이벤트 핸들러 내부에서 제거 가능
- 무명 이벤트 핸들러는 내부적으로
arguments.callee
를 사용하여 제거 가능
- 동일한 이벤트 핸들러 (무명 함수를 이벤트 핸들러로 등록한 경우 제거 불가함)
이벤트 핸들러 프로퍼티 방식 제거
: 벤트 핸들러는 프로퍼티에 null을 할당하여 제거 함
이벤트 객체
이벤트 객체
: 이벤트 발생시 이벤트에 관련된 정보를 담은 이벤트 객체가 동적으로 생성됨이벤트 핸들러 어트리뷰트의 이벤트 객체
- 생성된 이벤트 객체는 이벤트 핸들러(함수)의 첫 번째 인수로 전달됨
- 이벤트 객체를 전달 받을려면 이벤트 핸들러 함수의 첫번째 매개변수를 명시적 선언해야함 (이름은 상관 없음)
- 단, 이벤트 핸들러 어트리뷰트에서 할당하는 이벤트 핸들러에 전달하는 인수는 event 이름으로만 명식해야함
이벤트 객체의 상속구조
new Event()
,new FocusEvent('focus')
,new MouseEvent('click')
등의 이벤트 관련 생성자 함수에 의해서 해당 이벤트 객체를 만듦- Object - Event - UIEvent - MouseEvent - ...
- 이벤트 객체는 이벤트 관련 생성자 함수에 의해서 생성됨
- 이벤트 객체는 프로토타입으로 구성된 프로토타입 체인의 일원이 됨
- 이벤트 객체의 프로퍼티는 이벤트의 타입에 따라 달라짐
Event 인터페이스
: DOM 내에서 발생한 이벤트에 의해 생성되는 이벤트 객체(모든 이벤트 객체의 공통 프로퍼티 정의)하위 인터페이스
: 이벤트 타입에 따른 고유한 프로퍼티 정의
공통 프로퍼티
공통 프로퍼티 | 설명 | 타입 |
---|---|---|
type | 이벤트 타입 | string |
target | 이벤트를 발생시킨 DOM 요소 | DOM 요소 노드 |
currentTarget | 이벤트 핸들러가 바인딩된 DOM요소 | DOM 요소 노드 |
eventPhase | 이벤트 전파 단계 (0(없음), 1(캡쳐링 단계), 2(타깃 단계), 3(버블링 단계) | number |
bubbles | 이벤트를 버블링으로 전파하는지 여부 | boolean |
cancelable | preventDefault 메서드 호출하여 기본 동작 취소 가능한지 | boolean |
defaultPrevented | preventDefault 메서드를 호출하여 이벤트 취소 했는지 여부 | boolean |
isTrusted | 사용자의 행위에 의해 발생한 이벤트 인지 여부 (메서드를 통해 인위적으로 발생시키면 false) | boolean |
timeStamp | 이벤트가 발생한 | number |
- 버블링 하지 않는 이벤트, 이벤트 기본 동작을 취소 할수 없는 이벤트 :
- 포커스 이벤트 (focus/blur)
- 리소스 이벤트 (load/unload/abort/error)
- 마우스 이벤트 (mouseenter/ mouseleave)
마우스, 키보드 정보 취득
마우스 이벤트의 고유 프로퍼티
- 마우스 포인터의 좌표 정보를 나타내는 프로퍼티
- screenX/screenY, clientX/clientY(뷰포트 기준 좌표), pageX/pageY, offsetX/offsetY
- 버튼 정보를 나타내는 프로퍼티
- altKey, ctrlKey, shiftKey, button
- 마우스 포인터의 좌표 정보를 나타내는 프로퍼티
키보드 이벤트의 고유 프로퍼티
- altKey, ctrlKey, shiftKey, metaKey, key
- key 프로퍼티 값을 통해서 어떤키가 눌렸는지 알수 있고 그것을 조건으로 다음에 할 행동을 처리할 수 있음
이벤트 전파
이벤트 전파(event propagation)
DOM 요소 노드에서 발생한 이벤트는 DOM 트리를 통해 전파되는 현상- 생성된 이벤트 객체는 이벤트 타깃(이벤트를 발생시킨 DOM 요소)을 중심으로 DOM 트리틑 통해 전파됨
캡처링 단계
: 이벤트가 상위 요소 -> 하위 요소 방향으로 전파타깃 단계
: 이벤트가 이벤트 타깃에 도달버블링 단계
: 이벤트가 하위 요소 -> 상위요소 방향으로 전파이벤트 전파 순서
- 이벤트 발생시 이벤트 객체가 window에서 시작해서 이벤트 타깃(이벤트 발생한 곳) 방향으로 전파됨 (캡처링)
- -> 이벤트 객체가 이벤트 타겟에 도착함 (타깃)
- ->이벤트 객체가 이벤트 타깃에서 시작해서 window 방향으로 전파 (버블링)
이벤트 핸들러 어트리뷰트/프로퍼티 방식의 이벤트 핸들러
:- 타깃, 버블링 단계의 이벤트만 캐치
addEventListener 메서드 방식의 이벤트 핸들러
:- 캡처링, 타깃, 버블링 단계 모두 선별적으로 캐치 가능 (캡처링은 useCapture 매개변수에 true 설정 필요)
이벤트는 이벤트를 발생시킨 이벤트 타깃과 상위 DOM 요소에서도 캐치 가능함
이벤트 위임
이벤트 위임
: 어러 개의 하위 DOM 요소에 각각 이벤트 핸들러를 등록하는 대신, 하나의 상위 DOM 요소에 이벤트 핸들러를 등록하는 방법- 여러개의 이벤트 핸들러를 등록할 필요가 없어짐
- 동적으로 DOM 요소를 추가하더라도 이벤트 핸들러 등록 필요 X
- 하위 요소 모두에 적용되기 때문에, 원하는 요소의 이벤트만 처리하려고 하면
이벤트 타깃 검사
가 필요함Element.prototype.matches('선택자')
: 선택자에 의해 특정 노드를 탐색 가능한지 확인 함
- 이렇게 상위 요소에 이벤트를 바인딩 함으로서, 하위요소에서 이벤트 발생시 이벤트가 실제로 발생한 target과 이벤트를 감지하여 처리하는 currentTarget 프로퍼티는 달라질 수 있음
DOM 요소의 기본 동작 조작
event.preventDefault()
: DOM 요소의 기본 동작을 중단시킴 (a 요소 클릭시 href 이동, submit 새로고침, checkbox 체크, 해제 등...)event.stopPropagation()
: 이벤트 전파 중지- 하위 요소에서 사용시, 하위 요소 자체의 이벤트 핸들러만 작동하게 할수 있음
이벤트 핸들러 내부의 this
이벤트 핸들러 어트리뷰트 방식(HTML)
:- 핸들러 함수 내부의 this -> window (일반함수로 호출)
- HTML에서 어트리뷰트에 달린 핸들러 함수에 전달하는 this -> 이벤트를 바인딩한 DOM 요소
이벤트 핸들러 프로퍼티 방식, addEventListener 메서드 방식
:- 핸들러 함수 내부의 this -> 이벤트를 바인딩한 DOM 요소 (currentTarget 프로퍼티)
화살표 함수로 정의한 이벤트 핸들러
:- 핸들러 함수 내부의 this -> 상위 스코프 this
클래스에서 이벤트 핸들러 바인딩
:- constructor에서 클래스 메서드를 이벤트 핸들러로 사용하는 경우
- 클래스 메서드 내에서 정의한 this -> 이벤트를 바인딩한 DOM 요소
- this가 instance를 가리키려면,
bind(this)
,클래스 필드 + 화살표 함수로 정의하여 this사용
- constructor에서 클래스 메서드를 이벤트 핸들러로 사용하는 경우
이벤트 핸들러에 인수 전달
- 이벤트 핸들러 프로퍼티 방식, addEventListener 메서드 방식의 경우 함수 호출문이 아니라 함수 참조를 해야해서, 인수를 전달할 할 수 없음
- 방법01 :핸들러 내부에서 함수를 호출하면서 인수를 전달하면 됨
- 방법02 :이벤트 핸들러를 반환하는 함수를 호출하면서 인수 전달
// 방법 01 핸들러 함수를 할당할 때, 익명함수로 묶어 사용하기
const MIN_USER_NAME_LENGTH = 5;
const $input = document.querySelector("input[type=text]");
$input.onblur = () => {
checkUserNameLength(MIN_USER_NAME_LENGTH);
};
// 방법 02 핸들러 함수 자체에서 한번 더 거치게 하기
const MIN_USER_NAME_LENGTH = 5;
const $input = document.querySelector("input[type=text]");
const checkUserNameLength = (min) => (e) => {
// something to do ...
};
$input.onblur = checkUserNameLength(MIN_USER_NAME_LENGTH);
커스텀 이벤트
커스텀 이벤트
:이벤트 생성자 함수를 호출하여 명시적(의도적)으로 생성한 이벤트- -> 임의의 이벤트 타입 지정 가능
이벤트 생성자('eventType', {options})
- 보통은 커스텀이면 CustomEvent 생성자를 사용함
- eventType: 이벤트 타입을 나타내는 문자열, 기존 이벤트 타입 or 임의 문자열 둘다 가능
- 옵션 : bubbles, cancelable 프로퍼티를 갖는 객체로 해당 값(true or false)를 지정하여 변경 가능
- 해당 이벤트 생성자가 생성하는 이벤트 객체의 고유 프로퍼티를 넣어 해당 커스텀 이벤트의 고유 프로퍼티 값으로 지정할 수도 있음
- detail 프로퍼티를 만들어서 정보를 넣으면, 핸들러 함수에 e.detail로 정보를 사용할 수 있게 함
이벤트 생성자로 만든 이벤트 객체
- 기본적으로 bubbles, cancelable 프로퍼티의 값이 false로 됨 (버블링, preventDefault X)
- isTrusted 프로퍼티의 값이 언제나 false 임 (사용자 행위에 의한 자연스런 이벤트 객체는 true임)
커스텀 이벤트 디스패치
:- dispatchEvent 매서드로 이벤트를 발생시키는 행위 가능
- dispatchEvent 메서드 호출시 이벤트 객체를 인수로 전달 받은 이벤트 타입의 이벤트가 발생함
- dispatchEvent 메서드는 이벤트 핸들러를 동기 처리 방식으로 호출 함(즉, 이벤트 핸들러를 직접 호출하는 것임)
- 반드시, 커스텀 이벤트 객체 생성시 addEventListener 메서드 방식으로 이벤트 핸들러 등록 필요함