이번 포스팅에서 이벤트 핸들러 등록 방식에 대해 알아봅시다
🤔이벤트 핸들러 어트리뷰트 방식
- HTML요소의 어트리뷰트 중에는 이벤트에 대응하는 이벤트 핸들러 어트리뷰트가 있습니다.
- 이벤트 핸들러 어트리뷰트 값으로 함수 호출문 등의 문을 할당하면 이벤트 핸들러가 등록됩니다.
<!--index.html-->
<!--...-->
<body>
<button onclick="sayHi('Lee')">Click!</button>
<script>
function sayHi(name){
console.log(`Hi ${name}!`)
}
</script>
</body>
<!--...-->
- 주의할 점은 함수 참조가 아닌 함수 호출문 등의 “문”(statement)를 할당한다는 것이다.
- 이 방식은 더 이상 사용하지 않는 것이 좋다. html과 js의 관심사가 다르므로 혼재하는 것 보다는 분리하는 것이 좋다.
- 하지만 CBD(Component Based Development) 방식의 라이브러리는 이벤트 핸들러 어트리뷰트 방식으로 이벤트를 처리한다.
<!-- Angular -->
<button (click)="handleClick($event)">Click</button>
<!-- React -->
<button onClick={handleClick}>Click</button>
<!-- Svelte -->
<button on:click={handleClick}>Click</button>
<!-- Vue -->
<button v-on:click="handleClick($event)">Click</button>
🤔이벤트 핸들러 프로퍼티 방식
- window 객체와 Document, HTMLElement 타입의 DOM 노드 객체는 이벤트에 대응하는 이벤트 핸들러 프로퍼티를 가지고 있다.
- on접두사와 이벤트의 종류를 나타내는 이벤트 타입으로 이루어져 있다.
- 이벤트를 발생시킬 객체인 이벤트 타깃, 이벤트 종류를 나타내는 문자열인 이벤트 타입, 그리고 이벤트 핸들러를 지정할 필요가 있다
const $button = document.querySelector("#button");
$button.onclick = function(){console.log("click")}
//$button = 이벤트 타깃, onclikc = 이벤트 타입, function = 이벤트 핸들러
- 프로퍼티 방식은 HTML과 JS의 혼용 문제를 해결할 수 있지만, 하나의 이벤트 핸들러만 바인딩 할 수 있다는 단점이 있다.
- 이벤트 프로퍼티 방식으로 등록한 이벤트를 제거하려면 이벤트 핸들러 프로퍼티에 null값을 할당한다.
$button.onclick = function(){console.log("click")}
$button.onclick = null
🤔addEventListener 메서드 방식
- DOM Level2에서 EventTarget.prototype.addEventListener 메서드를 사용하여 이벤트 핸들러를 등록할 수 있다. 앞서 살펴본 어트리뷰트 방식과 프로퍼티 방식은 DOM Level 0 부터 제공되던 방식이다.
EventTarget.addEventListener('eventType', functionName[, useCapture])
- 첫 번째 매개변수로 이벤트의 종류, 두 번째 매개변수로 핸들러를, 세 번째 매개변수로 이벤트를 캐치할 전파 단계를 지정한다. 세번 째 매개변수를 생략하거나 false값을 지정하면 버블링 단계에서, 반대 상황에선 캡처링 단계에서 이벤트를 캐치한다.
const $button = document.querySelector("#button");
$button.addEventListener('click', function(){console.log("click")})
- 이벤트 핸들러 프로퍼티에 바인딩 된 핸들러에는 아무런 영향을 끼치지 않아, 만약 버튼 요소에 프로퍼티에 핸들러를 바인딩하고, addEventListener 메서드로 핸들러를 등록한다면 2개의 이벤트가 모두 호출된다.
- 이 방식 역시 여러개의 이벤트를 등록하는 것이 가능하다.
- removeEventListener 메서드로 등록한 이벤트를 제거할 수 있다.
const $button = document.querySelector("#button");
function handler(){
console.log("click")
}
$button.addEventListener('click', handler)
$button.removeEventListener('click', handler, true) //실패
$button.removeEventListener('click', handler) //성공
- 이벤트 제거는 같은 핸들러를 참조하여야 제거되기 때문에 무명 함수를 사용한다면 제거하는 것이 불가능하다.
const $button = document.querySelector("#button");
$button.addEventListener('click', ()=>{console.log("click")})
$button.removeEventListener('click', ()=>{console.log("click")) //실패
- 한 번만 이벤트 핸들러를 호출하기 위해선 다음과 같이 할 수 있다
const $button = document.querySelector("#button");
//기명 함수
$button.addEventListener('click', function foo(){
console.log("click")
$button.removeEventListener('click', foo);
})
//무기명 함수
//함수 자신을 가리키는 argument.callee를 사용하여 제거
$button.addEventListener('click', function (){
console.log("click")
$button.removeEventListener('click', arguments.callee);
})
'기술 서적 > 하루 30분 모딥다' 카테고리의 다른 글
[하루 30분 모던 자바스크립트 딥 다이브] 상속에 의한 클래스 확장 (0) | 2023.07.26 |
---|---|
[하루 30분 모던 자바스크립트 딥 다이브] 클래스 2 (0) | 2023.07.25 |
[하루 30분 모던 자바스크립트 딥 다이브] 클래스 (0) | 2023.07.24 |
[하루 30분 모던 자바스크립트 딥 다이브] 클로저의 캡슐화와 정보은닉 (0) | 2023.07.22 |
[하루 30분 모던 자바스크립트 딥 다이브] 클로저란 무엇인가 (0) | 2023.07.21 |