이벤트(event) 인터페이스는 DOM에서 발생하는 이벤트로, 사용자의 동작 혹은 프로그램에서 발생하는 특정한 상황을 의미한다.
이벤트 발생 → 사전에 정의된 특정 코드 실행 → 그 결과로 기능이 동작하거나, 화면이 변경되는 등의 변화 발생
HTML에서 발생하는 이벤트는 주로 마우스 및 입력양식에서 발생하며, 문서의 로딩과 관련된 특별한 이벤트를 포함한다.
대표적인 HTML Event는 다음과 같다. 더 많은 HTML Event는 여기에!
이벤트명 | 설명 |
---|---|
click | 클릭시 발생 |
change | 변동이 있을시 발생 |
focus | 포커스를 얻었을때 발생 |
keydown | 키를 눌렀을때 발생 |
keyup | 키에서 손을 땠을때 발생 |
load | 문서의 로드가 완료 되었을때 발생 |
unload | 문서가 언로드 되었을때 발생 |
resize | 윈도우 크기가 변경될 경우 발생 |
mouseover | 마우스가 특정 객체 위로 올려졌을 시에 발생 |
mousedown | 마우스를 클릭 했을때 발생 |
mouseout | 마우스가 특정 객체 밖으로 나갔을 때 발생 |
mousemove | 마우스가 움직였을 때 발생 |
mouseup | 마우스에서 손을 땟을때 발생 |
select | option 태그 등에서 선택을 했을때 발생 |
submit | 입력양식이 제출 요청 될때 발생 |
이벤트 핸들러는 이벤트 발생을 감지하고 처리할 코드를 수행하는 역할을 담당한다.
HTML 태그의 속성으로 지정하거나, JavaScript 파일에서 DOM Element의 속성에 콜백함수를 정의하는 형식으로 사용한다. 보편적으로 이벤트 핸들러는 이벤트 이름의 앞에 'on'을 붙여 사용한다.
이벤트를 감지하기 위한 HTML 태그의 속성에 이벤트 핸들럴를 할당한다.
<input type="button" value="Button" onclick="alert('버튼 클릭됨!!')"></input>
자바스크립트 코드를 사용해 DOM Element(= 특정 HTML Tag)를 선택해 속성으로 이벤트 발생시 호출될 콜백 메서드를 정의한다.
document.getElementById('b1').onclick = function() {alert("버튼 클릭됨!!")}
또는 addEventHandler()
를 이용해 이벤트 핸들러를 추가할 수 있다.
document.getElementById("id_name").addEventHandler("click", function(){ code });
표준 DOM Event에서 정의한 이벤트 흐름엔 3가지 단계가 있다.
① 캡처링 단계 : 이벤트가 하위 요소로 전파되는 단계
② 타깃 단계 : 이벤트가 실제 타깃 요소에 전달되는 단계
③ 버블링 단계 : 이벤트가 상위 요소로 전파되는 단계
아래 그림에서 <td />
태그를 클릭하면 이벤트가 최상위 조상부터 시작해 아래로 전파되는 캡처링 단계 → 이벤트가 타깃 요소에 도착해 실행되는 타깃 단계 → 마지막으로 다시 위로 전파되는 버블링 단계를 거친다.
DOM Event는 3가지 단계를 통해 요소에 할당된 이벤트 핸들러가 호출된다.
이벤트 버블링은 특정 화면 요소에서 이벤트가 발생했을 때, 해당 이벤트가 더 상위 요소들로 전달되어 가는 특성을 의미한다.
DOM은 기본적으로 트리 구조를 갖는다. 따라서 트리 구조에서 현재 요소보다 한 단계 위에 있는 요소를 상위요소라고 하며, body 태그가 최상위 요소가 된다.
⛔️ 거의 모든 이벤트는 버블링 된다.
여기서 중요한 포인트는 '거의' 이다.
focus
이벤트와 같이 버블링이 되지 않는 몇몇 이벤트를 제외하곤 대부분의 이벤트는 버블링 된다.
event.stopPropagation()
원하는 요소에서만 이벤트를 발생하게 하고 싶다면, event.stopPropagation()
를 통해 버블링을 중단할 수 있다. 이를 통해 클릭한 타깃만 이벤트가 발생하고, 상위 요소로 이벤트가 전파되는 것을 막아준다.
<form onclick="alert('버블링은 여기까지 도달하지 못합니다")">FORM
<div onclick="event.stopPropagation()">클릭해주세요.</div>
</form>
💡 한 요소의 이벤트 핸들러가 두개라면?
한 요소의 특정 이벤트를 처리하는 핸들러가 여러개라면, event.stopPropagation()를 통해 하나의 핸들러의 버블링을 멈추더라도 나머지 핸들러는 여전히 동작한다.
즉,
event.stopPropagation()
는 상위로 일어나는 버블링은 막아주지만, 같은 요소에 할당된 다른 핸들러들이 동작하는 건 막지 못한다.따라서 상위로 일어나는 버블링을 중단하고, 같은 요소에 할당된 다른 핸들러의 동작도 막으려면
event.stopImmediatePropagation()
를 사용하면 된다. 이 메서드를 사용하면 해당 요소에 할당된 이벤트를 처리하는 모든 핸들러의 동작이 중단된다.
❓ 이벤트 버블링 중단, 올바른가?
버블링은 매우 유용하므로, 버블링을 꼭 멈춰야 하는 상황이 아니라면 버블링을 막지 않는 것이 좋다.
👉event.stopPropagation()
을 사용한 영역은 ‘죽은 영역(Dead Zone)’이 되어버리기 때문이다.따라서 불가피하게 버블링을 막아야한다면,
event.stopPropagation()
대신 커스텀 이벤트 등을 사용해 이벤트 버블링을 통제하는 것이 좋다.
이에 반해 이벤트 캡쳐링은 최상위 요소부터 시작해 타깃 요소까지 아래로 전파되는 과정을 의미한다.
이벤트가 발생한 가장 안쪽 요소는 타깃(target) 요소라고 불리고,
event.target
을 통해 타깃 요소에 접근 할 수 있다.
부모 요소의 핸들러는 이 타깃요소를 통해 이벤트가 정확히 어디서 발생했는지 등에 대한 자세한 정보를 얻을 수 있다.
console.log(event)
를 찍어보면 target
과 currentTarget
이 있는 것을 알 수 있다.
비슷한 의미 같은데, 이 둘은 어떻게 다를까? event
객체에 속해있는 target
과 currentTarget
의 차이점에 대해 알아보자.
결론부터 말하면,
target은 실제 이벤트가 발생하는 요소이고,
currentTarget은 이벤트 리스너가 달린 요소이다.
<!--HTML-->
...
<body>
<ul>
<li>
<button id="oauth">
<span>Google</span>
</button>
<li>
</ul>
</body>
<script>
const googleOauthElement = document.querySelector('#oauth');
googleOauthElement.addEventListener('click', (e) => {
console.log(e.target);
console.log(e.currentTarget);
})
</script>
...
const onLogin = (e) => {
console.log(e.target);
console.log(e.currentTarget);
}
function APP() => {
...
<li>
<button onClick={onLogin}>
<span>Google</span>
</button>
<li>
...
}
그럼 다음과 같이 event.target은 자식 요소인 span을 리턴하고, event.currentTarget은 부모 요소인 button을 반환하는 것을 알 수 있다.
target은 실제 이벤트가 발생하는 요소이고,
currentTarget은 이벤트 리스너가 달린 요소이다.
💡 읽어볼 Article
※ 참고자료