이벤트

이벤트

이벤트 드리븐 프로그래밍

이벤트 : 무언가 일어났다는 신호

이벤트 핸들러 : 이벤트가 발생했을 때 실행되는 함수

이벤트 핸들러 등록 : 브라우저에게 이벤트 핸들러의 호출을 위임

브라우저가 행동을 감지해 이벤트를 발생 시킴

이벤트 드리븐 프로그래밍 : 이벤트 중심으로 프로그램의 흐름을 제어하는 프로그래밍 방식

이벤트 타입

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

이벤트 핸들러 등록

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

HTML 요소의 이벤트 핸들러 어트리뷰트에 값으로 문(statement)을 할당

각 어트리뷰트 이름은 'on + 이벤트 타입'

Click me function sayHi(name) { console.log(`Hi! ${name}.`); }

이벤트 핸들러 어트리뷰트 값은 암묵적으로 생성될 이벤트 핸들러의 몸체를 의미함

위 예에서 onclick="sayHi('dlwlrma')" 어트리뷰트는 파싱되어 다음과 같은 함수를 암묵적으로 생성 함

function onclick(event) { sayHi('dlwlrma'); }

생성한 함수는 이벤트 핸들러 어트리뷰트 이름과 동일한 키인 onclick 이벤트 핸들러 프로퍼티에 할당 함

함수의 참조를 할당하는 것이 아닌 함수 호출문을 할당하는 이유는 이벤트 핸들러에 인수를 전달하기 위함

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

window 객체, Document, HTMLElement 타입의 DOM 노드 객체는 이벤트에 대응하는 이벤트 핸들러 프로퍼티를 가짐

각 프로퍼티 키는 이벤트 핸들러 어트리뷰트의 이름과 같이 on + 이벤트타입

이벤트 핸들러 프로퍼티에 함수를 바인딩해서 이벤트 핸들러 등록

Click me const $button = document.querySelector('button'); $button.onclick = function () { console.log('clicked'); };

결과적으로 이벤트 핸들러 어트리뷰트와 동일하지만 하나의 프로퍼티에 두 개 이상의 이벤트 핸들러 등록을 하지 못하는 단점이 있음

어트리뷰트에 두 번 이상 핸들러를 등록 시 핸들러가 덮어 씌워짐

addEventListener 메서드 방식

DOM Level 2에서 도입된 EventTarget.prototype.addEventListener 메서드를 이용해 핸들러 등록

앞선 두 방식은 DOM Level 0부터 제공되던 방식

[EventTarget].addEventListener(['eventType'], [functionName] [, options]);

첫 번째 인자로 전달되는 이벤트 타입에는 접두사 on이 붙지 않음

마지막 인자는 다음의 프로퍼티를 갖는 객체 once : true이면 이벤트가 트리거 될 때 리스너가 자동으로 삭제됨 capture :true는 캡처링 당계에서 이벤트를 캐치, false는 버블링 단계에서 이벤트를 캐치 passive : true면 핸들러가 preventDefault를 호출하지 않음 option 객체가 아닌 false/true로 할당 시 capture의 값으로 지정됨

addEventListener 메서드 방식은 프로퍼티에 바인딩된 이벤트 핸들러에 아무 영향을 주지 않음

addEventListener 메서드 방식과 프로퍼티 바인딩 형식을 모두 사용해서 같은 이벤트에 핸들러 등록 시 두 핸들러 모두 작동함

addEventListener 메서드는 하나 이상의 핸들러 등록 가능, 등록된 순서대로 호출됨

단, 참조가 동일한 핸들러를 중복 등록 시 하나만 등록 됨

Click me const $button = document.querySelector('button'); $button.addEventListener('click'), function () { console.log('clicked'); });

이벤트 핸들러 제거

addEventListener로 등록한 핸들러는 removeEventListener 메서드를 사용해 제거 가능

removeEventListener에 전달한 인수가 addEventListener로 등록했던 인수와 동일하면 제거됨

인수가 동일해야 하기 때문에 무명 함수로 핸들러 등록 시 제거 할 수 없음

프로퍼티 방식으로 등록한 핸들러는 removeEventListener로 제거 불가 프로퍼티에 null을 할당해 제거

이벤트 객체

이벤트 발생 시 이벤트 정보를 담은 이벤트 객체가 동적으로 생성됨

생성된 이벤트 객체는 이벤트 핸들러의 첫 번째 인수로 전달됨

어트리뷰트 방식으로 이벤트 객체를 전달 받으려면 이벤트 핸들러의 첫 번째 매개변수 이름이 반드시 event여야 함

이벤트 객체도 생성자 함수에 의해 생성되어 프로토타입 체인의 일원이므로 상위 객체 프로토타입 프로퍼티를 상속받음

이벤트 전파

DOM 요소 노드에서 발생한 이벤트는 DOM 트리를 통해 전파됨

캡처링 : 상위 → 하위 방향으로 전파

버블링 : 하위 → 상위 방향으로 전파

이벤트 전파로 상위 DOM요소에서 이벤트 캐치 가능

버블링을 통해 전파되지 않는 이벤트들이 있지만 대체할 수 있는 이벤트가 존재하므로 캡처링 단계에서 이벤트를 캐치해야 할 경우는 거의 없음

버블링 안 됨 / 버블링 됨(대체) mouseenter / mouseover mouseleave / mouseout focus / focusin blur / focusout

이벤트 위임

상위 요소에 이벤트를 위임함으로써 이벤트 핸들러 등록을 효율적으로 관리 가능

bbubbu .active { color: red; } Apple Banana Orange 선택된 아이럼: apple const $fruits = document.querySelector('#fruits'); const $msg = document.querySelector('.msg'); function activate({ target }) { if (!target.matches('#fruits > li')) return; [...$fruits.children].forEach($fruit => { $fruit.classList.toggle('active', $fruit === target); $msg.textContent = target.id; }); } $fruits.addEventListener('click', activate);

이벤트 객체의 currentTarget 프로퍼티는 핸들러가 바인딩된 DOM 요소를 가리키고 target 프로퍼티는 이벤트를 발생시킨 DOM요소를 가리킴

DOM요소의 기본 동작 조작

기본 동작 중단

이벤트 객체의 preventDefault 메서드는 DOM 요소의 기본 동작을 중단 시킴

이벤트 전파 방지

stopPropagation

이벤트 핸들러 내부의 this

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

어트리뷰트 방식은 암묵적으로 새로운 함수가 만들어지고 그 함수의 몸체에 핸들러의 호출문이 들어가는 형식이므로 this는 중첩함수, 즉 일반 함수로써의 호출이 되어 전역객체가 할당됨

단, 인수로 this를 전달하면 새로 만든 함수 몸체에서의 this가 되므로 이 함수의 this가 됨. 이는 프로퍼티 메서드로 할당되는 함수이므로 this는 이벤트를 바인딩한 DOM요소를 가리킴

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

둘 모두 this는 이벤트를 바인딩한 DOM요소를 가리킴

단, 화살표 함수로 정의한 이벤트 핸들러 내부의 this는 상위 스코프의 this를 가리킴에 유의

클래스에서 이벤트 핸들러를 바인딩할 때 this에 주의해야 함

document 0 class App { constructor() { this.$button = document.querySelector('.btn'); this.count = 0; this.$button.onclick = this.increase.bind(this); } increase() { this.$button.textContent = ++this.count; } } new App();

클래스 필드에 할당한 화살표 함수를 핸들러로 등록해 핸들러 내부의 this가 인스턴스를 가리키도록 할 수 있지만 이 때 핸들러는 프로토타입 메서드가 아닌 인스턴스 메서드가 됨

이벤트 핸들러에 인수 전달

인수 전달은 함수 호출 시에 가능함

따라서 어트리뷰트 방식을 제외한 프로퍼티 방식, addEventListener 메서드 방식은 브라우저가 호출하기 때문에 인수를 전달할 수 없음

그러나 핸들러 내부에서 함수를 호출해 인수를 전달하거나 핸들러를 반환하는 함수를 호출해 인수를 전달 가능

document User name const MIN_USER_NAME_LENGTH = 5; const $input = document.querySelector('input[type=text]'); const $msg = document.querySelector('.message'); const checkUserNameLength = min => { $msg.textContent = $input.value.length < min ? `이름은 ${min}자 이상 입력해주세용` : ''; }; $input.onblur = () => { checkUserNameLength(MIN_USER_NAME_LENGTH); }

커스텀 이벤트

커스텀 이벤트 생성

이벤트 객체는 이벤트 생성자 함수로 생성 가능

생성자 함수로 명시적으로 생성한 이벤트 객체는 임의의 이벤트 타입을 지정 가능

from http://fffo.tistory.com/202 by ccl(A) rewrite - 2021-11-12 16:26:49