40 이벤트
이벤트 드리븐 프로그래밍
브라우저는 특정 사건이 발생하면 이를 감지하여 이벤트를 발생시킴
특정 타입 이벤트에 대해 반응하여 어떤 함수를 실행시킨다면, 해당 타입의 이벤트가 발생했을때 호출될 함수를 브라우저에게 알려 호출을 위임함
이벤트핸들러
이벤트가 발생했을때 호출될 함수
이벤트 핸들러 등록
이벤트 발생시 이벤트 핸들러의 호출을 브라우저에게 위임하는 것
//<button>Click me!</button>
const button=document.querySelector('button');
button.onclick=()=>{alert("누르셧군요");}
이벤트 타입
이벤트 종류를 나타내는 문자열
약 200가지의 이벤트가 있음
MDN참고바람….
이벤트 핸들러 등록
3가지 방식으로 등록할 수 있음
이벤트 핸들러 어트리뷰트 방식
HTML 어트리뷰트에 on접두사 + 이벤트 타입
어트리뷰트 값으로 함수 호출문 등 문을 할당하면 이벤트 핸들러가 등록된다.
//<button onclick="sayHi("lee")">click me</button>
function sayHI(name){
alert(`Hi ${name}`);
}
해당 함수가 어트리뷰트에 할당될 때는 다음과 같이 할당된다.
function onclick(event){
sayHI("Lee");
}
따라서 만약, 함수 호출문을 할당하여 반환되는 값이 있는 경우, 제대로 실행되지 않을 것이다.
이벤트 핸들러 프로퍼티 방식
DOM 노드객체는 이벤트에 해당하는 이벤트 핸들러 프로퍼티를 가지고 있음
//<button onclick="sayHi("lee")">click me</button>
const button=document.querySelector('button');
button.onClick=()=>{
console.log('button click');
}
동일한 이벤트에 대해 여러 이벤트 핸들러를 등록할 수 없음(갱신됨)
addEventListener방식
EventTarget.prototype.addEventListener메서드를 사용하여 이벤트 핸들러를 등록할 수 있다.
이벤트 타겟.addEventListener('eventType',이벤트 핸들러 함수, [,useCapture]);
이벤트 타입에는 다른 방식과 달리 on접두사를 사용하지 않음
또한, 마지막 접두사로 이벤트를 캐치할 이벤트 전파단계를 지정함(캡처링 또는 버블링)
false면 버블링에서 캐치, true면 캡처링에서 캐치
동일한 이벤트에 대해 여러 이벤트 핸들러를 등록할 수 있으며, 등록한 순서대로 작동함
이벤트 핸들러 제거
removEventListener로 제거할 수 있음
다만, 해당 인수가 동일해야함
무명함수를 등록하게 되면 제거가 불가능함
이벤트객체
이벤트가 발생하면 이벤트 객체가 동적으로 생성됨
생성된 이벤트 객체는 이벤트 핸들러의 첫번째 인수로 암묵적으로 전달됨
다만, 어트리뷰트 방식으로 등록하는 경우, 반드시 event라는 매개변수로 받아야함
이벤트 객체의 상속구조
Object → Event → …
의 구조로 상속
new 를 통해 event 객체 생성가능함
이벤트 객체의 공통 프로퍼티
Event.prototype의 프로퍼티들은 공통 프로퍼티임
type | 이벤트 타입 |
---|---|
target | 이벤트를 발생시킨 DOM요소 |
currentTarget | 이벤트 핸들러가 바인딩된 DOM요소 |
eventPhase | 이벤트 전파단계 |
0: 이벤트 없음 1: 캡처링 2: 타깃 3: 버블링 | |
bubbles | 이벤트를 버블링으로 전파하는지 여부 |
cancelable | preventDefault메서드를 사용하여 이벤트의 기본동작을 취소할 수 있는지 |
defaultPrevented | preventDefault를 통해 이벤트를 취소했는지 여부 |
isTrusted | 사용자의 행위에 의해 발생한 이벤트인지 여부 |
timeStamp | 이벤트가 발생한 시각(밀리초) |
마우스 정보 취득
click, dblclick, mousedown, mouseup, mousemove등 이벤트는 생성되는 MouseEvent타입의 객체를 통해 고유의 프로퍼티를 갖는다.
마우스 포인터 좌표정보 : screenX, screenY, ClientX,ClientY, pageX, pageY, offsetX, offsetY
버튼 정보를 나타내는 프로퍼티 : altKey, ctrlKey, shiftKey, button
clientX,clientY는 뷰포트를 기준으로 마우스 포인터 좌표를 나타냄
키보드 정보 획득
keydown, keyup등의 이벤트는
key, keycode, altKey 등 고유 프로퍼티를 가짐
이벤트 전파
DOM트리상의 이벤트는 DOM트리를 통해 전파됨
- 캡처링 : 상위→ 하위로 전파
- 타깃 : 해당 DOM요소에 도달
- 버블링 : 하위 → 상위로 전파
이벤트 객체는 window에서 만들어지므로, 해당 객체가 타깃까지 도착해야함 → 캡처링
타깃에 도착함 → 타깃
타깃에서 다시 window방향으로 전파 → 버블링
버블링 되지 않는 이벤트
- 포커스 이벤트 : focus/blur
- 리소스 이벤트 : load/unload/abort/error
- 마우스 이벤트 : mouseenter/mouseleave
버블링을 통해 전파되지 않으므로 캡처링에서 캡처해야함
이벤트 위임
상위요소에 이벤트를 위임하여 이벤트 핸들러를 등록할 수 있다.
그러면 currentTarget과 target이 다르게 된다.
DOM요소의 기본 동작
DOM요소는 기본적인 동작이 존재한다.
preventDefault는 해당 DOM요소의 기본동작을 중단시킨다.
document.querySelector('a').onclick=e=>{
e.preventDefault();
}
이벤트 전파 방지
stopPropagation은 이벤트 전파를 중지시킨다.
이를 사용하면 상위요소에 이벤트 위임을 할 수 없다.
이벤트 핸들러 내부의 this
이벤트 핸들러 어트리뷰트 방식
this는 전역객체를 가리킨다.
단, 인수로 전달한 this는 이벤트를 바인딩한 DOM요소를 가리킨다.
//<button onclick="handleClick(this)"/>
function handleClick(button){
console.log(button) //<button ...>
}
프로퍼티방식과 addEventListener방식
이벤트 핸들러 내부의 this는 이벤트를 바인딩한 DOM요소를 가리킴
// <button>click</button>
const but=document.querySelector('button');
but.onclick=function(e)=>{
console.log(this); // button
console.log(e.currentTarget) //button
console.log(this===e.currentTarget) //true
}
but.addEventListener('click',function(e)=>{
console.log(this); // button
console.log(e.currentTarget) //button
console.log(this===e.currentTarget) //true
}
다만 화살표 함수로 정의하게되면 다른 결과를 가져올 수 있다.
화살표 함수에는 this가 없기 때문이다.
// <button>click</button>
const but=document.querySelector('button');
but.onclick=function(e)=>{
console.log(this); //window
console.log(e.currentTarget) //button
console.log(this===e.currentTarget) //true
}
but.addEventListener('click',function(e)=>{
console.log(this); //window
console.log(e.currentTarget) //button
console.log(this===e.currentTarget) //true
}
커스텀 이벤트
CustomEvent 생성자로 생성가능하다.
해당 이벤트객체는 버블링 되지 않으며, preventDefault로 취소도 불가능하다.
가능하게 할려면 생성자 함수의 두번째 인자로 설정을 넘겨준다.
const custom=new CustomEvent('foo',{
bubbles:true,
cancelable:true
});
커스텀 이벤트의 프로퍼티 역시 동일한 방식으로 전달한다.
해당 커스텀 이벤트는 어트리뷰트 방식/프로퍼티 방식으로 등록이 불가능하고, addEventListener로 등록이 가능하다.
커스텀 이벤트 디스패치
커스텀 이벤트는 dispatchEvent메서들 이벤트를 발생시킬 수 있다.
이러면 동기방식으로 작동되어 직접 그 함수를 호출시킨 것과 같은 형태로 작동한다.
const button=document.querySelector('button');
const customEvent=new MouseEvent('click');
button.addEventListener('click',e=>{
console.log(e);
alert(`${e} clicked!`});
}
button.dispatchEvent(customEvent);