JS 공부 - 이벤트

이윤표·2024년 3월 24일
0

개요

이벤트 핸들러

  • 이벤트가 발생했을 때 브라우저에 의해 호출될 함수

이벤트 핸들러 등록

  • 이벤트 발생 시 브라우저에게 이벤트 핸들러의 호출을 위임하는 것
  • 3가지 방법이 있다.

💡 브라우저에게 함수 호출을 위임하는 이유
사용자가 언제 이벤트를 발생 (ex. 버튼 클릭)시킬지 모르기 때문에 개발자가 명시적으로 함수를 호출하지 않고 브라우저에게 함수 호출을 위임한다.
브라우저는 처리해야 할 특정 사건이 발생하면 이를 감지(ex. 버튼 클릭 감지)하여 이벤트를 발생 시킬 수 있다.

const $button = document.querySelector('button');

$button.onclick = () => { console.log('button click'); };

이벤트 핸들러 프로퍼티에 함수를 할당하면 해당 이벤트가 발생했을 때 (버튼 클릭했을 때) 할당한 함수가 브라우저에 의해 호출된다.


이벤트 핸들러 등록

1. 어트리뷰트 방식

  • 등록방법
    • HTML 요소 어트리뷰트 중에는 이벤트 핸들러 어트리뷰트가 있는 데 값으로 함수 호출문을 할당한다.
  • 이벤트 핸들러 어트리뷰트 이름: on + 이벤트 타입 (ex. onclick )
<button onclick="sayHi('lee')">버튼</button>
<script>
	function sayHi(name) {
		console.log(name);
	}
</script>

🚨 함수 참조가 아닌 함수 호출문을 할당?
이벤트 핸들러를 등록할 때 콜백 함수처럼 함수 참조를 등록해야 브라우저가 이벤트 핸들러를 호출할 수 있다. 만약 함수 호출문을 등록하면 함수 평가 결과가 이벤트 핸들러로 등록된다. 이 때, 함수를 반환하는 고차함수 호출문을 등록하면 문제가 없지만 함수가 아닌 값을 반환하는 함수 호출문을 등록하면 브라우저가 이벤트 핸들러를 호출할 수 없다.

이벤트 핸들러 어트리뷰트 값은 사실 암묵적으로 생성될 이벤트 핸들러의 함수 몸체를 의미한다.

즉, onclick="sayHi('lee')" 어트리뷰트는 파싱되어 다음과 같은 함수를 암묵적으로 생성한다.

function onClick(event) {
	sayHi('lee');
}

이후 생성된 함수를 onclick 이벤트 핸들러 프로퍼티에 할당한다. (결국 이벤트 핸들러 프로퍼티 방식과 동일)

💡 왜 이렇게 동작하는 지?
이벤트 핸들러에 인수를 전달하기 위해! 어트리뷰트 값으로 함수 참조를 할당하려면 인수를 전달하기 곤란하다.

React 나 Vue.js 같은 프레임워크에서는 이벤트 핸들러 어트리뷰트 방식으로 이벤트를 처리한다.

2. 프로퍼티 방식

  • 등록방법:
    • window 객체, DOM 노드 객체는 이벤트에 대응하는 이벤트 핸들러 프로퍼티를 가지고 있다. 이 이벤트 핸들러 프로퍼티에 함수를 바인딩한다.
  • 이벤트 핸들러 프로퍼티 키 이름: on + 이벤트 타입 (ex. onclick )
<button>버튼</button>
<script>
	const $button = document.querySelector('button');
	
	// 이벤트 핸들러 프로퍼티에 이벤트 핸들러 바인딩
	$button.onclick = function () {
		console.log('클릭')
	}
</script>

이벤트 핸들러를 등록하려면 아래 3가지를 지정해야 한다.

  • 이벤트 타깃 (event target): 이벤트를 발생시킬 객체 (ex. $button )
  • 이벤트 타입 (event type): 이벤트 종류 (ex. click )
  • 이벤트 핸들러: (ex. function () { console.log() } )

이벤트 핸들러 프로퍼티에는 하나의 이벤트 핸들러만 바인딩할 수 있다.

3. addEventListener 메서드 방식

  • 등록 방법
EventTarget.addEventListener('eventType', functionName [, useCapture])
<button>버튼</button>
<script>
	const $button = document.querySelector('button');
	
	$button.addEventListener('click', function () {
		console.log('클릭');
	});
</script>

addEventListener 메서드는 이벤트 핸들러 프로퍼티 방식과 달리 하나 이상의 이벤트 핸들러를 등록할 수 있다. (등록된 순서대로 호출)

단, 동일한 이벤트를 중복 등록하면 하나만 등록된다.

const $button = document.querySelector('button');

const handleClick = () => console.log('클릭');

// 중복 등록 시 핸들러 하나만 등록
$button.addEventListener('click', handleClick);
$button.addEventListener('click', handleClick);

이벤트 핸들러 제거

이벤트 핸들러 프로퍼티 방식에서

  • 제거 방법
    • 이벤트 핸들러 프로퍼티에 null 를 할당한다. (removeEventListenr 메서드 ❌)
// 이벤트 핸들러 등록
$button.onclick = handleClick;
    
// 이벤트 핸들러 제거
$button.onclick = null;

addEventListener 메서드 방식에서

  • 제거 방법
    • removeEventListenr 메서드 사용 (인수는 등록과 동일)
    • addEventListener 메서드에 전달한 인수와 removeEventListener 메서드에 전달한 인수가 일치해야 한다.
// 이벤트 핸들러 등록
$button.addEventListener('click', handleClick);
    
// 이벤트 핸들러 제거
$button.removeEventListener('click', handleClick);

💡 removeEventListener 의 인수로 전달한 이벤트 핸들러와 addEventListener 인수로 전달한 이벤트 핸들러는 동일해야 하기 때문에 만약 익명함수로 이벤트 핸들러를 등록했다면 이벤트를 제거할 수 없다.

단, 기명 이벤트 핸들러 내부에서 removeEventListener 메서드를 호출하여 이벤트 핸들러를 제거할 수 있다. 따라서 이 경우 이벤트 핸들러는 단 한번만 호출된다.

// 버튼을 여러번 클릭해도 한 번만 이벤트 핸들러 호출
$button.addEventListener('click', function foo() {
	console.log('클릭');
  
    // 이벤트 핸들러를 제거한다.	
    $button.removeEventListener('click', foo);
}

참고

profile
프론트엔드 개발자 지망생

0개의 댓글