이벤트는(event)는 무언가 일어났다는 신호이다. 모든 DOM 노드는 이런 신호를 만들어 낸다. 참고로, 이벤트는 DOM에만 한정되진 않는다.
마우스 이벤트:
폼 요소 이벤트:
키보드 이벤트:
문서 이벤트:
css 이벤트:
이벤트에 반응하려면 이벤트가 발생했을 때 실행되는 함수인 핸들러를 할당해야 한다.
핸들러는 사용자의 행동에 어떻게 반응할지를 자바스크립트 코드로 표현한 것입니다.
핸들러는 여러 가지 방법으로 할당할 수 있다.
HTML 속성
HTML 안의 on<event>
속성에 핸들러를 할당할 수 있다.
아래 같이 input 태그의 onclick 속성에 click 핸들러를 할당하는 것과 같다.
<input value="클릭해 주세요" onclick="alert('클릭!') type="button">
버튼을 클릭하면 onclick 안의 코드가 실행된다.
여기서 주의해야 할 것은 속성값 내에서 사요된 따옴표이다. 속성값 전체가 큰따옴표로 둘러싸여 있기 때문에 작은 따옴표로 둘러쌓는다.클릭!")"과 같이 속성값 내부에 또 큰따옴표를 쓰면 코드가 작동하지 않는다.
긴 코드를 HTML 속성값으로 사용하는 것은 추천하지 않는다. 만약 코드가 길다면, 아래와 같이 함수를 만들어서 이를 호출하는 방법을 추천한다.
<script>
function countRabbits() {
for(let i=1; i<=3; i++) {
alert(`토끼 ${i}마리`);
}
}
</script>
<input type="button" onclick="countRabbits()" value="토끼를 세봅시다!">
DOM 프로퍼티
DOM 프로퍼티 on<event>
을 사용해도 핸들러를 할당할 수 있다.
<input id="elem" type="button" value="클릭해 주세요.">
<script>
elem.onclick = function() {
alert('감사합니다.');
};
</script>
핸들러를 HTML 속성을 사용해 할당하면, 브라우저는 속성값을 이용해 새로운 함수를 만든다. 그리고 생성된 함수를 DOM 프로퍼티에 할당한다.
따라서 DOM 프로퍼티를 사용해 핸들러를 만든 위 예시는 HTML 속성을 사용해 만든 바로 위쪽 예시와 동일하게 작동한다.
onclick 프로퍼티는 단 하나밖에 없기 때문에, 복수의 이벤트 핸들러를 할당할 수 없다.
아래 예시와 같이 핸들러를 하나 더 추가하면, 기존 핸들러는 덮어씌워진다.
<input type="button" id="elem" onclick="alert('이전')" value="클릭해 주세요.">
<script>
elem.onclick = function() { // 기존에 작성된 핸들러를 덮어씀
alert('이후'); // 이 경고창만 보입니다.
};
</script>
핸들러를 제거하고 싶으면 elem.onclick = null 같이 null을 할당하면 된다.
핸들러 내부에 쓰인 this의 값은 핸들러가 할당된 요소이다.
아래 예시의 this.innerHTML에서 this는 button 이므로 버튼을 클릭하면 버튼 안의 컨텐츠가 얼럿창에 출력된다.
<button onclick="alert(this.innerHTML)">클릭해 주세요.</button>
이벤트를 다룰 때는 아래 주의사항을 항상 염두에 둬야한다.
이미 존재하는 함수를 직접 핸들러에 할당하는 예시를 살펴보자
<script>
function sayThanks() {
alert('감사합니다!');
}
elem.onclick = sayThanks;
</script>
이때 함수는 sayThanks처럼 할당해야 한다. sayThanks()를 할당하면 동작하지 않는다.
<script>
// 올바른 방법
button.onclick = sayThanks;
// 틀린 방법
button.onclick = sayThanks();
</script>
sayThanks() 같이 괄호를 덧붙이는 것은 함수를 호출하겠다는 것을 의미한다. 위 예시의 마지막 줄처럼 sayThanks()를 프로퍼티에 할당하면 함수 호출의 결과값이 할당된다.
함수 sayThanks가 아무것도 반환하지 않는다면 onclick 프로퍼티엔 undefined가 할당되므로 이벤트가 원하는 대로 동작하지 않는다.
그런데, HTML 속성값에는 괄호가 있어야 한다.
<input type="button" id="button" onclick="sayThanks()">
브라우저는 속성값을 읽고, 속성값을 함수 본문으로 하는 핸들러 함수를 만들기 때문에 이런 차이가 발생한다.
브라우저는 onclick 프로퍼티에 새로운 함수를 할당한다.
HTML 속성과 DOM 프로퍼티를 이용한 이벤트 핸들러 할당 방식엔 근본적인 문제가 있다. 하나의 이벤트에 복수의 핸들러를 할당할 수 없다는 문제이다.
버튼을 클릭하면 버튼을 강조하면서 메시지를 보여주고 싶다고 해 보자
그럼 두 개의 이벤트 핸들러가 필요하다. 하지만 기존 방법으로는 프로퍼티가 덮어씌워 진다는 문제가 있다.
<script>
input.onclick = function() { alert(1); }
// ...
input.onclick = function() { alert(2); } // 이전 핸들러를 덮어씀
</script>
이럴 때 사용할 수 있는게 addEventListener와 removeEventListener이다.
<script>
element.addEventListener(event, handler, [options]);
</script>
event
이벤트 이름(예: "click")
handler
핸들러 함수
options
아래 프로퍼티를 갖는 객체
핸들러 삭제는 removeEventListener로 한다.
삭제는 동일한 함수만 할 수 있다.
<script>
element.removeEventListener(event, handler, [options]);
</script>