# 이벤트
사용자의 입력에 따라 추가 동작을 구현할 수 있는 방법
# DOM 이벤트
# 마우스 이벤트
- click
- 요소 위에서 마우스 왼쪽 버튼을 눌렀을 때(터치스크린이 있는 장치에선 탭 했을 때) 발생합니다.
- contextmenu
- 요소 위에서 마우스 오른쪽 버튼을 눌렀을 때 발생합니다.
- mouseover / mouseout – 마우스 커서를 요소 위로 움직였을 때, 커서가 요소 밖으로 움직였을 때 발생합니다.
- mousedown / mouseup
- 요소 위에서 마우스 왼쪽 버튼을 누르고 있을 때, 마우스 버튼을 뗄 때 발생합니다.
- mousemove – 마우스를 움직일 때 발생합니다.
# 폼 요소 이벤트
- submit
– 사용자가
<form>
을 제출할 때 발생합니다. - focus
– 사용자가
<input>
과 같은 요소에 포커스 할 때 발생합니다.
# 키보드 이벤트
- keydown / keyup – 사용자가 키보드 버튼을 누르거나 뗄 때 발생합니다.
# 문서 이벤트
- DOMContentLoaded – HTML 이 전부 로드 및 처리되어 DOM 생성이 완료되었을 때 발생합니다.
# CSS 이벤트
- transitionend – CSS 애니메이션이 종료되었을 때 발생합니다.
# 이벤트 핸들러
- 이벤트에 반응하는 함수
- 이벤트에 이벤트가 발생했을 때 실행되는 함수인 핸들러(handler) 를 할당해야 한다.
- 사용자의 행동에 어떻게 반응할지를 자바스크립트 코드로 표현한 것
# HTML 속성
HTML 안의 on<event>
속성에 핸들러를 할당할 수 있습니다.
버튼을 클릭하면 onclick 안의 코드가 실행됩니다.
<input value="클릭해 주세요." onclick="alert('클릭!')" type="button">
1
핸들러 내부에 쓰인 this 의 값 → 핸들러가 할당된 요소
<button onclick="alert(this.innerHTML)">클릭해 주세요.</button>
1
this 는 button
- HTML 태그 중간에 자바스크립트가 들어가 있으면 어색
- 긴 코드
함수를 만들어서 이를 호출하는 방법 사용
- 이벤트 핸들러는 함수로 호출 → 핸들러 내부의 this 는 전역객체 혹은 undefined
<script>
function countRabbits() {
for(let i=1; i<=3; i++) {
alert(`토끼 ${i}마리`);
}
}
</script>
<input type="button" onclick="countRabbits()" value="토끼를 세봅시다!">
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
HTML 속성은 대·소문자를 구분하지 않음
ONCLICK
은onClick
이나onCLICK
과 동일하게 작동- 속성값은 대개 onclick 같이 소문자로 작성
# DOM 프로퍼티
elem.onclick
<input id="elem" type="button" value="클릭해 주세요.">
<script>
elem.onclick = function() {
alert('감사합니다.');
};
</script>
1
2
3
4
5
6
2
3
4
5
6
HTML 속성 과 동일하게 동작합니다. 따라서
- onclick 프로퍼티는 단 하나 → 복수의 이벤트 핸들러를 할당 불가능
- 핸들러를 하나 더 추가하면, 기존 핸들러는 덮어씌워 집니다.
핸들러 제거
-elem.onclick = null
# setAttribute 로 핸들러를 할당 X
<body>
를 클릭하면 에러가 발생합니다.- 속성은 항상 문자열이기 때문에, 함수가 문자열로 됨.
document.body.setAttribute('onclick', function() { alert(1) });
1
# DOM 프로퍼티는 대·소문자를 구분
핸들러 할당 시 elem.onclick
을 써야한다.
elem.ONCLICK
은 쓸 수 없다.
# 함수를 핸들러에 직접 할당할 때 주의점
# 1 프로퍼티 할당
function sayThanks() {
alert('감사합니다!');
}
elem.onclick = sayThanks; // sayThanks()를 할당하면 동작하지 않습니다.
1
2
3
4
5
2
3
4
5
# 2 속성 할당
괄호가 있어야함.
- 브라우저는 속성값을 읽고, 속성값을 함수 본문으로 하는 핸들러 함수를 만들기 때문
<input type="button" id="button" onclick="sayThanks()">
1
# addEventListener
HTML 속성 / DOM 프로퍼티 이벤트 핸들러 할당 방식의 문제
- 하나의 이벤트에 복수의 핸들러 할당 불가
# 핸들러 추가
element.addEventListener(event, handler, [options]);
1
event
이벤트 이름(예: "click")handler
핸들러 함수options
아래 프로퍼티를 갖는 객체once
: true, 이벤트가 트리거 될 때 리스너가 자동으로 삭제됩니다.capture
- (버블링/캡처링)어느 단계에서 이벤트를 다뤄야 하는지를 알려주는 프로퍼티
- 호환성 유지
options
를 객체가 아닌false
/true
로 할당 가능{capture: false/true}
와 동일
passive
: true, 리스너에서 지정한 함수가 preventDefault() 를 호출하지 않습니다.
# 핸들러 삭제
element.removeEventListener(event, handler, [options]);
1
함수는 똑같게 생겼지만 그럼에도 불구하고 다른 함수이기 때문에 제거할 수 없다.
elem.addEventListener( "click" , () => alert('감사합니다!'));
// ....
elem.removeEventListener( "click", () => alert('감사합니다!'));
1
2
3
2
3
핸들러에 할당한 함수를 사용해야 한다.
function handler() {
alert( '감사합니다!' );
}
input.addEventListener("click", handler);
// ....
input.removeEventListener("click", handler);
1
2
3
4
5
6
7
2
3
4
5
6
7
변수에 핸들러 함수를 저장해야
- 지울 수 있다.
- addEventListener 로 할당한 핸들러를 불러올 수 있다
# 어떤 이벤트는 addEventListener 를 써야만 동작
DOMContentLoaded
- 문서를 읽고 DOM 트리 생성이 완료되었을 때 트리거되는 이벤트
// 이 얼럿창은 절대 뜨지 않습니다.
document.onDOMContentLoaded = function() {
alert("DOM이 완성되었습니다.");
};
// 이 얼럿창은 제대로 뜹니다.
document.addEventListener("DOMContentLoaded", function() {
alert("DOM이 완성되었습니다.");
});
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
- addEventListener 는 좀 더 범용적
# this
- 이벤트 핸들러는 콜백 함수이지만
- this 는 이벤트 리스너에 바인딩된 요소를 가리킨다.
- 이벤트 객체의 currentTarget 프로퍼티와 같다.
# 이벤트 객체
click
이벤트가 발생- 마우스 포인터 위치 필요
keydown
이벤트가 발생- 어떤 키가 눌렸는지 등에 대한 상세한 정보가 필요
# 이벤트 발생
브라우저는
- 이벤트 객체(event object) 생성
- 이벤트 객체에 이벤트에 관한 상세한 정보를 넣은다.
- 핸들러에 인수 형태로 전달합니다.
이벤트 객체로부터 포인터 좌표 정보를 얻어내는 예시
<input type="button" value="클릭해 주세요." id="elem">
<script>
elem.onclick = function(event) {
// 이벤트 타입과 요소, 클릭 이벤트가 발생한 좌표를 보여줌
alert(event.type + " 이벤트가 " + event.currentTarget + "에서 발생했습니다.");
alert("이벤트가 발생한 곳의 좌표는 " + event.clientX + ":" + event.clientY +"입니다.");
};
</script>
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
이벤트 객체에서 지원하는 프로퍼티
event.type
이벤트 타입- 예시 "click"
event.currentTarget
이벤트를 처리하는 요소- 일반적으로 콜백의 this 가 가리키는 값과 같음
- 화살표 함수 핸들러 / 함수를 다른 곳에 바인딩한 경우
- this 는 currentTarget 이 아님
- event.currentTarget 을 직접 사용해야 함.
event.clientX
/event.clientY
- 포인터 관련 이벤트에서, 커서의 상대 좌표(모니터 기준 좌표가 아닌, 브라우저 화면 기준 좌표 – 옮긴이)
이벤트 타입에 따라 이벤트 객체에서 제공하는 프로퍼티는 다르다.
# HTML 핸들러 안의 이벤트 객체
<input type="button" onclick="alert(event.type)" value="이벤트 타입">
1
- 브라우저는 속성을 읽고
function(event) { alert(event.type) }
같은 핸들러를 만들어 내기 때문 - 생성된 핸들러 함수의 첫 번째 인수는 이벤트 객체
# 객체 형태의 핸들러와 handleEvent
addEventListener 를 사용하면 함수뿐만 아니라 객체를 이벤트 핸들러로 할당할 수 있습니다.
<button id="elem">클릭해 주세요.</button>
<script>
let obj = {
// 이벤트가 발생하면 객체에 구현한 handleEvent 메서드가 호출
handleEvent(event) {
alert(event.type + " 이벤트가 " + event.currentTarget + "에서 발생했습니다.");
}
};
elem.addEventListener('click', obj);
</script>
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
<button id="elem">클릭해 주세요.</button>
<script>
class Menu {
handleEvent(event) {
switch(event.type) {
case 'mousedown':
elem.innerHTML = "마우스 버튼을 눌렀습니다.";
break;
case 'mouseup':
elem.innerHTML += " 그리고 버튼을 뗐습니다.";
break;
}
}
}
let menu = new Menu();
elem.addEventListener('mousedown', menu);
elem.addEventListener('mouseup', menu);
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
하나의 객체에서 두 개의 이벤트를 처리하기 위해,
- addEventListener 를 사용할 때는 요소에 타입을 정확히 명시해 주어야 한다
- 위 예시에서 menu 객체는 오직 mousedown 와 mouseup 이벤트에만 응답하고, 다른 타입의 이벤트에는 응답하지 않습니다.
handleEvent 메서드가 모든 이벤트를 처리할 필요는 없습니다.
- 이벤트 관련 메서드를 handleEvent 에서 호출해서 사용할 수도 있습니다.
<button id="elem">클릭해 주세요.</button>
<script>
class Menu {
handleEvent(event) {
// mousedown -> onMousedown
let method = 'on' + event.type[0].toUpperCase() + event.type.slice(1);
this[method](event);
}
onMousedown() {
elem.innerHTML = "마우스 버튼을 눌렀습니다.";
}
onMouseup() {
elem.innerHTML += " 그리고 버튼을 뗐습니다.";
}
}
let menu = new Menu();
elem.addEventListener('mousedown', menu);
elem.addEventListener('mouseup', menu);
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# Reference
- https://ko.javascript.info/introduction-browser-events
- https://gitlab.com/siots-study/topics/-/wikis/dom