이벤트 버블링
이벤트 버블링이란 위의 그림처럼 가장 깊게 중첩된 요소(3)에 이벤트가 발생했을 때, 이벤트가 위로 전달되는 것을 의미한다.
3번 요소, 2번 요소, 1번 요소에 그 이벤트에 대한 핸들러가 있다면, 3번->2번->1번 핸들러 순으로 실행된다.
<!doctype html>
<body>
<style>
body * {
margin: 10px;
border: 1px solid blue;
}
</style>
<form onclick="alert('form')">FORM
<div onclick="alert('div')">DIV
<p onclick="alert('p')">P</p>
</div>
</form>
</body>
가장 안쪽의 <p> 태그를 클릭하면 우선 p태그에 할당된 onclick 핸들러가 작동된다.
그리고 div->form 순서대로 작동한다. document 객체를 만날 때까지 각 요소에 할당된 onclick 핸들러가 동작한다.
즉 위의 코드를 클릭하면 3개의 alert가 뜬다.
event.target과 this의 차이점
event.target은 실제 이벤트가 시작된 ‘타깃’ 요소, 즉 버블링이 진행되어도 변하지 않는다. this는 ‘현재’ 요소로, 현재 실행 중인 핸들러가 할당된 요소를 참조한다.
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<link rel="stylesheet" href="example.css">
</head>
<body>
<form id="form">FORM
<div>DIV
<p>P</p>
</div>
</form>
<script src="script.js"></script>
</body>
</html>
form.onclick = function(event) {
event.target.style.backgroundColor = 'yellow';
setTimeout(() => {
alert("target = " + event.target.tagName + ", this=" + this.tagName);
event.target.style.backgroundColor = ''
}, 0);
};
form 태그를 눌렀을 때 이벤트가 실행되므로 this는 form으로 고정이다.
p 태그를 눌렀을 때는 target = P, this=FORM가 출력되고, div 태그를 눌렀을 때는 target = DIV, this=FORM 가 alert로 출력되는 것을 확인할 수 있다.
Bubbling 중단하기
<!doctype html>
<body>
<style>
body * {
margin: 10px;
border: 1px solid blue;
}
</style>
<form onclick="alert('form')">FORM
<div onclick="alert('div')">DIV
<p onclick="event.stopPropagation()"">P
</p>
</div>
</form>
</body>
event.stopPropagation() 메서드를 사용하면 해당 요소를 클릭해도 이벤트 버블링이 발생하지 않으며, 따라서 부모 요소의 핸들러도 호출이 되지 않는다.
이벤트 캡처링
이벤트 캡처링이란 이벤트 버블링과 다르게 제일 상단에 있는 요소에서 아래로 이벤트가 내려오는 것을 말한다.
이벤트 흐름의 3단계 흐름
1. 캡처링 단계 - 이벤트가 하위요소로 전파되는 단계
2. 타깃 단계 - 이벤트가 실제 타깃 요소에 전달되는 단계
3. 버블링 단계 - 이벤트가 상위 요소로 전파되는 관계
위의 사진에서 td 요소를 클릭하면, 최상위 조상에서 시작해서 아래로 전파되는 캡처링 단계, 이벤트가 타깃 요소에 도착하는 타깃단계, 그리고 다시 위로 전파되는 버블링 단계를 거치게 된다.
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>js</title>
<style></style>
</head>
<body>
<form>FORM
<div>DIV
<p>P</p>
</div>
</form>
<script>
for (let al of document.querySelectorAll('*')){
al.addEventListener('click', e => alert(`캡처링 : ${al.tagName}`),true)
al.addEventListener('click', e => alert(`버블링 : ${al.tagName}`))
}
</script>
</body>
</html>
이렇게 설정하고 p태그를 클릭해 보면 상위 HTML 요소부터 타깃 요소인 p태그까지 내려왔다가 다시 올라가는 것을 확인할 수 있다.
+
- 이벤트 객체는 이벤트 리스너 내에서만 접근할 수 있다.
- preventDefault() 메서드를 사용하여 이벤트의 기본 동작을 방지하지만 이벤트 흐름을 중지하지는 않는다.
- stopPropagation() 메서드를 사용하여 DOM 트리를 통한 이벤트 흐름을 중지하지만 브라우저 기본 동작을 취소하지는 않는다.
참고
'프로그래밍 언어 > JavaScript' 카테고리의 다른 글
[JS] this 키워드 (0) | 2024.04.25 |
---|---|
[JS] id를 반환받지 않아도 Script에서 바로 지목할 수 있다. (0) | 2024.04.24 |
브라우저 객체 모델 (0) | 2023.09.30 |
DOM으로 Form 요소 접근 (0) | 2023.09.29 |
DOM 기초 정리 (0) | 2023.09.28 |