이벤트 핸들러
이벤트가 발생했을때 브라우저에 의해 호출될 함수를 이벤트 핸들러 라고 한다. 브라우저에게 이벤트 핸들러의 호출을 위임하는것을 이벤트 핸들러 등록이라고 한다. window, document, HTMLElement 타입의 객체는 onclick과 같이 특정 이벤트에 대응하는 다양한 이벤트 핸들러 프로퍼티를 가진다.
자주 사용하는 이벤트 타입
이벤트의 종류를 나타내는 문자열이다. 약 200가지가 존재하고, 아래는 자주쓰는 이벤트들. 최근에 사용하지않는것들은 생략하였음.
click : 마우스 버튼클릭
dblclick : 마우스 더블클릭
mousedown : 마우스버튼 눌렀을때
mousemove : 마우스 커서 움직였을때
mouseenter : 마우스 커서를 HTML요소 안으로 이동했을 때 (버블링되지 않음)
mouseover : 마우스 커서를 HTML 요소 안으로 이동했을 때 (버블링됨)
mouseleave : 마우스 커서를 HTML 요소 밖으로 이동했을 때 (버블링되지 않음)
mouseout : 마우스 커서를 HTML 요소 밖으로 이동했을 때 (버블링됨)
keydown : 모든 키를 눌렀을때 (문자, 특수문자, 숫자, enter 키를 누를때는 연속발생하나, 그 외는 1번만 발생)
keyup : 누르고 있던 키를 놓았을 때
focus : HTML요소가 포커스를 받았을 때 (버블링되지 않음)
blur : HTML요소가 포커스를 잃었을 때 (버블링되지 않음)
focusin : HTML요소가 포커스를 받았을 때 (버블링됨)
focusout : HTML요소가 포커스를 잃었을 때 (버블링됨)
submit : form요소 내 input(text, checkbox, radio), select 필드(textarea 제외)에서 엔터키를 눌렀을 때, 또는 submit 버튼을 클릭했을 때 (이벤트는 form 요소에서 발생한다)
input : input, select, textarea 요소의 값이 입력되었을 때
change : input, select, textarea 요소의 값이 변경되었을 때 *HTML요소가 포커스를 잃었을때 사용자 입력이 종료되었다고 인식하여 발생한다. 입력중일때는 input 이벤트가 발생하고, 값이 변경되면 change이벤트가 발생한다.
readystatechange : HTML문서의 로드와 파싱상태를 나타내는 document.readyState 프로퍼티 값('loading, interactive, complete가 변경될 때)
DOMContentLoaded : HTML 문서의 로드와 파싱이 끝나고 DOM 생성이 완료되었을때
resize: 윈도우크기를 리사이즈할때 연속적으로 발생 (window객체에서만 발생)
scroll : document 또는 HTML요소를 스크롤할때 연속적으로 발생
load : DOMContentLoaded 이벤트 발생 이후, 모든 리소스 로딩이 완료되었을 때
unload : 리소스가 언로드될 때 (ex-새 웹페이지를 요청한경우)
abort : 리소스 로딩이 중단되었을 때
error : 리소스 로딩이 실패 했을 때
이벤트 핸들러 등록 : 어트리뷰트 방식
어트리뷰트 방식으로 이벤트 핸들러를 등록할수있다. 어트리뷰트값으로 함수 호출문 등의 문을 할당하면 등록된다.
결과적으로는 DOM 노드 객체의 이벤트 핸들러 프로퍼티로 변환되므로 원리는 프로퍼티 방식과 같다.
<button onclick="console.log('rumi'); console.log('double')">print rumi</button>
// 여러개의 문을 할당할수있다
이 어트리뷰트는 파싱되어 암묵적으로 함수를 생성하고, 어트리뷰트 이름과 동일한 키 onclick 이벤트 핸들러 프로퍼티에 할당한다.
function onclick(e){
console.log('rumi');
}
이벤트 핸들러 등록 : 프로퍼티 방식
이벤트 타겟(button), 이벤트타입(onclick), 이벤트 핸들러(function)를 지정한다.
하나의 이벤트 핸들러만 바인딩할수있다는 단점이 있다. 여러개를 바인딩하면 마지막에 바인딩된 핸들러에 의해 재할당된다.
<button class="test-button">click!</button>
<script>
const button = document.querySelector('.test-button');
button.onclick = function(){
console.log('click me');
}
button.onclick = null; // 제거
</script>
제거하기 위해서는 이벤트 핸들러 프로퍼티에 null을 할당하면 된다.
이벤트 핸들러 등록 : addEventListener 메서드 방식
EventTarget.prototype.addEventListener('eventType', functionName) 메서드를 사용한다.
const button = document.querySelector('.test-button');
button.addEventListener('click', ()=>{
console.log('addEventListener 방식')
})
// 등록한 이벤트 핸들러를 참조할 수 없으므로(무명함수) removeEventListener로 제거 불가능
addEventListener메서드는 하나이상의 핸들러를 등록할 수 있고, 등록된 순서대로 호출된다.
만약 프로퍼티방식과 addEventListener 메서드방식으로 등록된 핸들러가 여러개라면, 서로 영향을 주지 않고 모두 호출된다.
핸들러를 제거하려면 EventTarget.prototype.removeEventListener 메서드를 사용한다. 인수로 전달한 이벤트핸들러는 addEventListener 메서드에 인수로 전달한 등록 이벤트핸들러와 같은 함수여야 한다. 따라서 무명함수를 등록하면 제거할수없다.
함수 자신을 가리키는 arguments.callee를 사용하면 제거할 수 있지만, 코드최적화에 좋지않고 strick mode에서 사용 금지이므로 그냥 이런게 있구나 알아만 두자.
이벤트 객체의 공통 프로퍼티
Event 인터페이스의 이벤트 관련 프로퍼티는 모든 이벤트 객체가 상속받는 공통 프로퍼티다.
type : 이벤트타입
target : 이벤트를 발생시킨 DOM 요소
currentTarget : 이벤트 핸들러가 바인딩된 DOM요소
eventPhase : 이벤트 전파 단계 ( 0:없음 1:캡쳐링 2:타깃 3:버블링 )
bubbles : 이벤트를 버블링으로 전파하는지 여부.
(focus/blur, load/unload/abort/error, mouseenter/mouseleave는 기본적으로 버블링하지않는다.)
cancelable : preventDefault 메서드를 호출하여 이벤트 기본동작을 취소할수있는지 여부
(focus/blur, load/unload/abort/error, dbclick/mouseenter/mouseleave는 false로 취소할 수 없다.)
defaultPrevented : preventDefault 메서드를 호출하여 이벤트를 취소했는지 여부
isTrusted : 사용자의 행위에 의해 발생한 이벤트인지 여부 (인위적으로 발생시킨 이벤트일경우 false)
timeStamp : 이벤트가 발생한 시각 (1970/01/01/00:00:00부터 경과한 밀리초)
이벤트 전파
이벤트 객체는 이벤트를 발생시킨 DOM요소인 이벤트 타깃을 중심으로 DOM트리를 통해 전파된다.
캡쳐링 단계 : window로부터 트리를 타고 내려와 상위 요소에서 하위요소 방향으로 전파
타깃 단계 : 이벤트가 이벤트타깃에 도착
버블링 단계 : 이벤트가 하위 요소에서 상위요소 방향으로 전파 (거품은 위로 올라가~)
**addeventListener 메서드는 세 단계 모두를 캐치할수있지만,
어트리뷰트/프로퍼티 방식으로 등록한 이벤트핸들러는 타깃/버블링 단계만 캐치 가능하다.
target vs currentTarget
event.target은 선택된 요소이고, currentTarget은 이벤트가 바인딩되어있는 요소이다.
상위 DOM 요소에 이벤트를 바인딩하면 하위 요소에 일일이 이벤트 핸들러를 등록할 필요가 없다. 이를 이벤트 위임이라고 한다.
이벤트 전파 방지
e.stopPropagation() : 이벤트 전파를 중지시킨다. 상위 요소에서 이벤트를 캐치할 수 없다. 하위 DOM 요소의 이벤트를 개별적으로 처리하기위해 사용한다.
이벤트 고유 동작 중단
e.preventDefault() : a 태그나 submit 타입 등의 버튼은 고유의 동작을 가진다. 이를 중단시킨다.
'[STUDY] 스터디 > Deep Dive JS' 카테고리의 다른 글
js 비동기 프로그래밍, Ajax와 HTTP (0) | 2023.02.06 |
---|---|
js 타이머 (0) | 2023.01.28 |
DOM (0) | 2023.01.26 |
js 브라우저 렌더링과정 (0) | 2023.01.22 |
js Set과 Map (0) | 2023.01.14 |