공부공부/JS 딥다이브

[js 딥다이브] 40장 이벤트

고생쨩 2024. 2. 18. 10:01
728x90

이벤트

이벤트 드리븐 프로그래밍

  1. 이벤트 핸들러 : 이벤트가 발생됐을때 호출할 함수
  2. 이벤트 핸들러 등록 : 이벤트가 발생했을때 브라우저에게 이벤트 핸들러의 호출을 위임

이벤트 타입

마우스

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

키보드

이벤트 타입 이벤트 발생 시점
keydown 모든 키를 눌렀을 때 발생한다. ※ control, option, shift, tab, delete, enter, 방향 키와 문자, 숫자, 특수 문자 키를 눌렀을 때 발생한다. 단, 문자, 숫자, 특수 문자, enter 키를 눌렀을 때는 연속적으로 발생하지만 그 외의 키를 눌렸을 때는 한 번만 발생한다.
keypress 문자 키를 눌렀을 때 연속적으로 발생한다. ※ control, option, shift, tab, delete, 방향 키 등을 눌렀을 때는 발생하지 않고 문자, 숫자, 특수 문자, enter키를 눌렀을 때만 발생한다. 폐지(deprecated)되었으므로 사용하지 않을 것을 권장한다.
keyup 누르고 있던 키를 놓았을 때 한 번만 발생한다. ※ keydown 이벤트와 마찬가지로 control, option, shift, tab, delete, enter, 방향 키와 문자, 숫자, 특수 문자 키를 놓았을 때 발생한다.

포커스

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

focusin, focusout 이벤트 핸들러를 이벤트 핸들러 프로퍼티 방식으로 등록하면 크롬, 사파리에서 정상 동작하지 않는다. focusin, focusout 이벤트 핸들러는 addEventListener 메서드 방식을 사용해 등록해야 한다.

이벤트 타입 이벤트 발생 시점
submit 1. form 요소 내의 input(text, checkbox, radio), select 입력 필드(textarea 제외)에서 엔터키를 눌렀을 때 2. form 요소 내의 submit 버튼(
reset form 요소 내의 reset 버튼을 클릭했을 때(최근에는 사용 안 함)

이벤트 타입 이벤트 발생 시점
input input(text, checkbox, radio), select, textarea 요소의 값이 입력되었을 때
change input(text, checkbox, radio), select, textarea 요소의 값이 변경되었을 때 ※ change 이벤트는 input 이벤트와는 달리 HTML 요소가 포커스를 잃었을 때 사용자 입력이 종료되었다고 인식하여 발생한다. 즉, 사용자가 입력을 하고 있을 때는 input 이벤트가 발생하고 사용자 입력이 종료되어 값이 변경되면 change 이벤트가 발생한다.
readystatechange HTML 문서의 로드와 파싱 상태를 나타내는 document.readyState 프로퍼티 값(‘loading’, ‘interactive’, ‘complete’)이 변경될 때

DOM 뮤테이션

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

뷰 이벤트

이벤트 타입 이벤트 발생 시점
resize 브라우저 윈도우(window)의 크기를 리사이즈할 때 연속적으로 발생한다. ※ 오직 window 객체에서만 발생한다.
scroll 웹페이지(document) 또는 HTML 요소를 스크롤할 때 연속적으로 발생한다.

리소스 이벤트

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

기타 이벤트
책에서 생략된 부분 많음.
(touch, composition, mediastream, animation 등등)
https://developer.mozilla.org/ko/docs/Web/API/Event

이벤트 핸들러 등록

이벤트 핸들러 어트리뷰트 방식
이벤트 핸들러 어트리뷰트 값은 사실 암묵적으로 생성될 이벤트 핸들러의 함수 몸체를 의미한다.(자체적으로 이벤트 핸들러 프로퍼티에 할당)

<button onclick="handleClick">Click me!</button>
<!-- Angular -->
<button (click)="handleClick($event)">Save</button>
{ /* React */ }
<button onClick={handleClick}>Save</button>
<!-- Svelte -->
<button on:click={handleClick}>Save</button>
<!-- Vue.js -->
<button v-on:click="handleClick($event)">Save</button>

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

//타깃,   타입,      핸들러
$button.onclick = function () {
  console.log('button click');
};

addEventListener 메서드 방식
target.addEventListener(type, handler, useCapture);

$button.addEventListener('click', function () {
  console.log('button click');
});

이벤트 핸들러 제거

$button.removeEventListener('click', handleClick);

//이벤트 핸들러 프로퍼티 방식으로 등록한 경우
$button.onclick = null;

이벤트 객체

이벤트 발생시 이벤트 객체가 동적으로 생성되고 이벤트 핸들러의 첫번째 인수로 전달됨.

function showCoords(e) {
  $msg.textContent = `clientX: ${e.clientX}, clientY: ${e.clientY}`;
}
// Event 생성자 함수를 호출하여 foo 이벤트 타입의 Event 객체를 생성한다.
let e = new Event('foo');
console.log(e);

// Event {isTrusted: false, type: "foo", target: null, ...}
console.log(e.type); // "foo"
console.log(e instanceof Event); // true
console.log(e instanceof Object); // true

// FocusEvent 생성자 함수를 호출하여 focus 이벤트 타입의 FocusEvent 객체를 생성한다.
e = new FocusEvent('focus');
console.log(e);

// FocusEvent {isTrusted: false, relatedTarget: null, view: null, ...}

// MouseEvent 생성자 함수를 호출하여 click 이벤트 타입의 MouseEvent 객체를 생성한다.
e = new MouseEvent('click');
console.log(e);

// MouseEvent {isTrusted: false, screenX: 0, screenY: 0, clientX: 0, ... }

// KeyboardEvent 생성자 함수를 호출하여 keyup 이벤트 타입의 KeyboardEvent 객체를 생성한다.
e = new KeyboardEvent('keyup');
console.log(e);

// KeyboardEvent {isTrusted: false, key: "", code: "", ctrlKey: false, ...}

// InputEvent 생성자 함수를 호출하여 change 이벤트 타입의 InputEvent 객체를 생성한다.
e = new InputEvent('change');
console.log(e);

// InputEvent {isTrusted: false, data: null, inputType: "", ...}

프로토타입 체인으로 상위 이벤트로 연결됨.
ex) click -> MouseEvent -> UIEvent -> Event

공통 프로퍼티 설명 타입
type 이벤트 타입
target 이벤트를 발생시킨 DOM 요소
currentTarget 이벤트 핸들러가 바인딩된 DOM 요소
eventPhase 이벤트 전파 단계 0: 이벤트 없음, 1: 캡처링 단계, 2: 타깃 단계, 3: 버블링 단계
bubbles 이벤트를 버블링으로 전파하는지 여부. 다음 이벤트는 bubbles: false로 버블링하지 않는다. ■ 포커스 이벤트 focus/blur ■ 리소스 이벤트 load/unload/abort/error ■ 마우스 이벤트 mouseenter/mouseleave
cancelable preventDefault 메서드를 호출하여 이벤트의 기본 동작을 취소할 수 있는지 여부. 다음 이벤트는 cancelable: false로 취소할 수 없다. ■ 포커스 이벤트 focus/blur ■ 리소스 이벤트 load/unload/abort/error ■ 마우스 이벤트 dblclick/mouseenter/mouseleave
defaultPrevented preventDefault 메서드를 호출하여 이벤트를 취소했는지 여부
isTrusted 사용자의 행위에 의해 발생한 이벤트인지 여부. 예를 들어, click 메서드 또는 dispatchEvent 메서드를 통해 인위적으로 발생시킨 이벤트인 경우 isTrusted는 false다.
timeStamp 이벤트가 발생한 시각(1970/01/01/00:00:0부터 경과한 밀리초)

이벤트 전파

  1. 캡처링 단계 – 이벤트가 하위 요소로 전파되는 단계
  2. 타깃 단계 – 이벤트가 실제 타깃 요소에 전달되는 단계
  3. 버블링 단계 – 이벤트가 상위 요소로 전파되는 단계

이벤트 위임

이벤트에 반응이 필요한 DOM 요소(실제 이벤트가 동작하는 el)에 한정하여 이벤트 핸들러가 실행되도록 이벤트 타깃을 검사할 필요가 있다.

DOM 요소의 기본 동작 조작

//기본동작 중단
e.preventDefault();

// 이벤트 전파 중단
e.stopPropagation(); 

이벤트 핸들러 내부의 this

이벤트 핸들러 어트리뷰트 방식
전역 객체 window를 가르킴.
단, 인수로 전달 받았을때는 이벤트를 바인딩한 DOM 요소

이벤트 핸들러 프로퍼티 방식과 addEventListener 메서드 방식
이벤트를 바인딩한 DOM 요소
화살표 함수인 경우 상위 스코프의 this
클래스 사용시 bind 메서드로 class의 this 전달. 또는 화살표 함수 사용.

이벤트 핸들러에 인수 전달

책 내용 잘못됨. addEventListner도 가능.

obj.addEventListener('click', (event)=> 
  callback(event, '인수');
);

커스텀 이벤트

<!DOCTYPE html>
<html>
<body>
 <button class="btn">Click me</button>
 <script>
 const $button = document.querySelector('.btn');
 // 버튼 요소에 foo 커스텀 이벤트 핸들러를 등록
 // 커스텀 이벤트를 디스패치하기 이전에 이벤트 핸들러를 등록해야 한다.
 $button.addEventListener('foo', e => {
 // e.detail에는 CustomEvent 함수의 두 번째 인수로 전달한 정보가 담겨 있다.
 alert(e.detail.message);
 });
 // CustomEvent 생성자 함수로 foo 이벤트 타입의 커스텀 이벤트 객체를 생성
 const customEvent = new CustomEvent('foo', {
 detail: { message: 'Hello' } // 이벤트와 함께 전달하고 싶은 정보
 });
 // 커스텀 이벤트 디스패치
 $button.dispatchEvent(customEvent);
 </script>
</body>

이 포스팅은 쿠팡 파트너스 활동의 일환으로, 이에 따른 일정액의 수수료를 제공받습니다.