공부한 내용을 정리한 글입니다
내용에 오류가 있거나 더 좋은 의견이 있다면 댓글로 남겨주세요.
배움에 큰 도움이 됩니다. 🖋
removeEventListener로 제거 가능한 이벤트 핸들러
addEventListener로 등록한 이벤트 핸들러는 removeEventListener로 제거할 수 있다.
이 때 등록할 때 사용한 것과 동일한 함수를 전달해야 제거가 가능하므로 다음 같은 상황에선 제거되지 않는다.
- 불가 : 전달한 인수가 일치하지 않는 경우
const $submitButton = document.getElementById('submitButton')
const handleClickSubmitButton = ()=> {
event.preventDefault(); // 기본 제출 동작 방지
console.log('폼 제출');
}
$submitButton.addEventListener('submit', handleClickSubmitButton);
setTimeout(() => {
// 전달한 인수가 달라 이벤트 제거 실패
$submitButton.removeEventListener('submit', handleClickSubmitButton, true);
// 이벤트 제거 성공
$submitButton.removeEventListener('submit', handleClickSubmitButton);
console.log('5초 후 제출 이벤트 제거');
}, 5000);
- 불가 : 무명 함수를 등록할 경우
const $submitButton = document.getElementById('submitButton')
// 이벤트 핸들러를 제거하려면 해당 핸들러에 대한 참조를 변수나 자료구조에 저장하고 있어야 한다.
$submitButton.addEventListener('submit', () => {
event.preventDefault();
console.log('폼 제출');
});
- 불가 : 이벤트 프로퍼티 방식으로 등록한 이벤트 핸들러의 경우
const $submitButton = document.getElementById('submitButton')
const handleClickSubmitButton = ()=> {
event.preventDefault(); // 기본 제출 동작 방지
console.log('폼 제출');
}
// 이벤트 핸들러 프로퍼티 방식으로 핸들러 등록
$submitButton.onclick = handleClickSubmitButton;
setTimeout(() => {
// 등록 방식이 달라 제거 실패
$submitButton.removeEventListener('submit', handleClickSubmitButton);
// 대신 null을 할당해 제거할 수 있다
$submitButton.onclick = null
console.log('5초 후 제출 이벤트 제거');
}, 5000);
반면 이름이 있는 함수 내에서 해당 이벤트를 제거하거나, arguments.callee를 사용하는 경우는 이벤트 핸들러 제거가 가능하다.
- 가능 : 이름있는 함수 내에서 removeEventListener를 호출하는 경우
const $submitButton = document.getElementById('submitButton')
$submitButton.addEventListener('submit', function handleClickSubmitButton() {
event.preventDefault();
console.log('폼 제출');
// 대신, 이럴 경우 이벤트 핸들러는 단 한 번만 호출된다
$submitButton.removeEventListener('click', handleClickSubmitButton)
});
- 가능 : 무명 함수 내에서 arguments.callee를 사용해 핸들러를 제거하는 경우
const $submitButton = document.getElementById('submitButton')
$submitButton.addEventListener('submit', function () {
event.preventDefault();
console.log('폼 제출');
// 그러나 argument.callee는 strict mode에서 사용할 수 없으며 코드 최적화를 방해할 수 있다.
// 가급적 이벤트 핸들러의 참조를 변수나 자료구조에 저장해 제거하는 것이 권장된다.
$submitButton.removeEventListener('click', argument.callee)
});
이벤트 객체의 상속 구조
이벤트가 발생하면 이벤트의 유형에 따라 다양한 이벤트 객체가 생성된다. 위 도식의 Event, UIEvent 등은 모두 생성자 함수로, 'new Event()'와 같이 생성자 함수 호출을 통해 이벤트 객체를 생성할 수 있다.
- 생성자 함수 호출로 이벤트 객체 생성
const event = new Event('surprise')
console.log(event)
이벤트 프로퍼티 중 target, currentTarget은 항상 헷갈리니까 한 번 더 정리해본다.
- target
이벤트를 발생시킨 DOM 요소 - currentTarget
이벤트 핸들러가 바인딩된 DOM 요소
import React from 'react';
const ClickExample = () => {
const handleClick = (event) => {
console.log('Target Element:', event.target); // <a> 태그
console.log('Current Target Element:', event.currentTarget) // <div> 태그
};
render() {
return (
<div onClick={handleClick}>
<a href="#">Click me1</a>
<a href="#">Click me2</a>
<a href="#">Click me3</a>
</div>
);
}
}
export default ClickExample;
또한, 키보드 이벤트 중 keyup은 한글 입력 시 이벤트 핸들러가 두 번 호출되는데 이 때 keyup 대신 keydown을 사용해 해결할 수 있다.
DOM 트리를 통해 이루어지는 이벤트 전파
이벤트는 DOM 트리의 노드에서 발생하며, 트리를 통해 전파된다.
이벤트 핸들러를 addEventListener로 등록하면 캡쳐링, 타깃, 버블링 단계의 이벤트를 선별적으로 캐치할 수 있지만, 어트리뷰트나 프로퍼티 방식으로 등록한 경우 타깃과 버블링 단계의 이벤트만을 잡아낼 수 있다.
캡처링 단계 : <td>를 클릭하면 이벤트가 window에서 <td> 방향으로 전파된다.
타겟 단계 : 이벤트 객체가 이벤트를 발생시킨 타겟요소 <td>에 도착해 리스너를 시작한다.
버블링 단계 : <td>에서 최상위 요소인 window로 다시 이벤트를 전파한다.
자주 사용하는 DOM 요소 조작 메서드
- e.preventDefault()
a 태그를 클릭하면 href에 연결된 링크로 이동하거나 checkbox / radio 요소를 클릭하면 체크,해제 되는 등 DOM 요소에는 저마다 기본 동작이 있다. preventDefault는 이러한 기본 동작을 중단시킬 수 있는 메서드 - e.stopPropagation()
하위 DOM 요소가 자신이 발생시킨 이벤트 전파를 중단시킬 수 있게 하는 메서드. 각 DOM 요소는 자신에게 바인딩된 이벤트 핸들러만 실행할 수 있도록 한다.
참고
책 : 모던 자바스크립트 딥다이브
'Java Script' 카테고리의 다른 글
Set, Map 어디에 사용할까? (1) | 2023.11.03 |
---|---|
실행 컨텍스트 (0) | 2023.10.27 |
[Yarn Berry] 말도 안되게 타입스크립트 에러 많이 뜰 때 (0) | 2023.08.08 |
[ Typescript ] 타입스크립트 Docs_Reference_Type Compatibility (0) | 2023.07.14 |
[ Typescript ] 타입스크립트 Docs_Classes (0) | 2023.06.25 |
댓글