*이 필기는 웹 프로그래밍 튜토리얼에서 보고 작성합니다.
1. 이벤트 드리븐 프로그래밍
브라우저는 처리해야할 특정 사건(클릭, 스크롤 등)이 발생했을 때 이를 감지해 이벤트를 발생시킨다. 이러한 이벤트에 대응해서 호출하고 싶은 함수가 있을 것이다. 이런 이벤트가 발생했을 때 호출될 함수를 이벤트 핸들러라고 한다. 그리고 브라우저에게 이벤트 핸들러가 호출될 수 있게 하는것을 이벤트 핸들러 등록이라고 한다.
<!DOCTYPE html>
<html>
<head>
<title>Document</title>
</head>
<body>
<button>Click me!</button>
<script>
const $button = document.querySelector('button');
// 사용자가 버튼을 클릭하면 함수를 호출하도록 요청
$button.onclick = () => { alert('button click'); };
</script>
</body>
</html>
위에서 보았듯이, 이벤트 핸들러 프로퍼티에 함수를 할당하면 해당 이벤트가 발생했을 때 할당한 함수가 호출된다.
이와 같이 프로그램의 흐름을 이벤트 중심으로 제어하는 프로그래밍 방식을 이벤트 드리븐 프로그래밍이라 한다.
2. 이벤트 타입
이벤트 타입은 이벤트의 종류를 나타내는 문자열이다. 에를 들어, 이벤트 타입 'click'은 사용자가 마우스 버튼을 클릭했을 때 발생하는 이벤트를 나타낸다.
다음은 다양한 이벤트들을 기록해놓은 사이트이다.
https://developer.mozilla.org/ko/docs/Web/Events
3. 이벤트 핸들러 등록
특정 이벤트가 발생했을 때 브라우저에 의해 호출되는 함수가 이벤트 핸들러이다. 브라우저에게 호출을 위임하는 것을 이벤트 핸들러 등록이라고 하는데 방법이 총 3가지가 있다고 한다.
이벤트 핸들러 어트리뷰트 방식
<!DOCTYPE html>
<html>
<head>
<title>Document</title>
</head>
<body>
<button onclick="sayHi('Lee')">Click me!</button>
<script>
function sayHi(name) {
console.log(`Hi! ${name}`);
}
</script>
</body>
</html>
HTML과 자바스크립트는 분리되어 있는게 좋기 때문에 권장되는 방법은 아니다.
이벤트 핸들러 프로퍼티 방식
<!DOCTYPE html>
<html>
<head>
<title>Document</title>
</head>
<body>
<button>Click me!</button>
<script>
const $button = document.querySelector('button');
// 이벤트 핸들러 프로퍼티에 이벤트 핸들러를 바인딩
$button.onclick = function () {
console.log('button click');
};
</script>
</body>
</html>
이벤트를 발생시킬 객체인 이벤트 객체 - 버튼 요소
이벤트의 종류를 나타내는 문자열인 이벤트 타입 - 'click'
이벤트 핸들러 - handleClick 함수
이벤트 핸들러 프로퍼티에 하나의 이벤트 핸들러만 바인딩할 수 있다는 단점이 있다.
addEventListenter 메서드 방식
EventTarget.prototype.addEventListener 메서드를 사용하여 이벤트 핸들러를 등록할 수 있다.
첫 번째 매개변수에는 이벤트의 종류를 나타내는 이벤트 타입을 전달한다. 위와는 다르게 접두사 'on'을 붙이지 않는다.
두 번째 매개변수에는 이벤트 핸들러를 전달한다.
마지막 매개변수에는 이벤트 전파 단계를 지정한다. 생략하거나 false의 경우에는 버블링 단계에서 캐치하고 true의 경우에는 캡처링 단계에서 캐치한다.
<!DOCTYPE html>
<html>
<head>
<title>Document</title>
</head>
<body>
<button>Click me!</button>
<script>
const $button = document.querySelector('button');
$button.addEventListener('click', function () {
console.log('button click');
});
</script>
</body>
</html>
4. 이벤트 핸들러 제거
addEventListener 메서드로 등록한 이벤트 핸들러를 제거하려면 EventTarget.prototype.removeEventListener 메서드를 사용한다. 전달한 인수가 동일해야 제거된다.
<!DOCTYPE html>
<html>
<head>
<title>Document</title>
</head>
<body>
<button>Click me!</button>
<script>
const $button = document.querySelector('button');
const handleClick = () => console.log('button click');
// 이벤트 핸들러 등록
$button.addEventListener('click', handleClick);
// 이벤트 핸들러 제거
// addEventListener 메서드에 전달한 인수와 removeEventListener 메서드에
// 전달한 인수가 일치하지 않으면 이벤트 핸들러가 제거되지 않는다.
$button.removeEventListener('click', handleClick, true); // 실패
$button.removeEventListener('click', handleClick); // 성공
</script>
</body>
</html>
5. 이벤트 객체
이벤트가 발생하면 이벤트에 관련된 다양한 정보를 담고 있는 이벤트 객체가 동적으로 생성된다. 생성된 이벤트 객체는 이벤트 핸들러의 첫 번째 인수로 전달된다.
<!DOCTYPE html>
<html>
<head>
<title>Document</title>
</head>
<body>
<p>클릭하시오. 클릭한 곳의 좌표가 표시됩니다.</p>
<em class="message"></em>
<script>
const $msg = document.querySelector('.message');
// 클릭 이벤트에 의해 생성된 이벤트 객체는 이벤트 핸들러의 첫 번째 인수로 전달한다.
function showCoords(e) {
$msg.textContent = `X: ${e.clientX}, Y: ${e.clientY}`;
}
document.onclick = showCoords;
</script>
</body>
</html>
- 클릭 이벤트에 의해 생성된 이벤트 객체는 이벤트 핸들러의 첫 번째 인수로 전달되어 매개변수 e에 암묵적으로 할당된다. 브라우저가 이벤트 핸들러를 호출할 때 이벤트 객체를 인수로 전달하기 때문이다.
- 따라서 이벤트 객체를 받을 매개변수를 따로 선언해줘야한다.
- 이름은 다른거로 사용해도 상관없다.
이벤트 객체의 공통 프로퍼티
https://developer.mozilla.org/ko/docs/Web/API/Event
마우스 정보 취득
https://developer.mozilla.org/ko/docs/Web/API/MouseEvent
키보드 정보 취득
https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent
6. DOM 요소의 기본 동작 조작
DOM 요소의 기본 동작 중단
a요소를 클릭하면 href에 지정된 링크로 이동하고, checkbox 또는 radio 요소를 클릭하면 체크 또는 해제된다.
이벤트 객체의 preventDefault 메서드는 이러한 DOM 요소의 기본 동작을 중단시킨다.
<!DOCTYPE html>
<html>
<head>
<title>Document</title>
</head>
<body>
<a href="https://www.google.com/"></a>
<script>
document.querySelector('a').onclick = e => {
// a 요소의 기본 동작을 중단한다.
e.preventDefault();
};
</script>
</body>
</html>
이벤트 전파 방지
이벤트 객체의 stopPropagation 메서드는 이벤트 전파를 중단시킨다.
여기까지 입니다 - 틀린 점이 있다면 꼭 지적해주세요!