Notice
Recent Posts
Recent Comments
Link
«   2024/11   »
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
Tags
more
Archives
Today
Total
관리 메뉴

코딩세상

JavaScript - 이벤트 버블링과 캡쳐링, 이벤트 위임 본문

Javascript

JavaScript - 이벤트 버블링과 캡쳐링, 이벤트 위임

필륭 2023. 3. 28. 15:15

이벤트의 개념과 종류

이벤트란?

- 웹 페이지에서 발생하는 사건을 의미합니다.


이벤트의 종류

 - 마우스 클릭, 키보드 입력, 스크롤 등 유저가 웹페이지에서 동작할 수 있는 기능을 전부 통틀어서 나타낼 수 있으며, 각각의 이벤트는 서로 다른 동작을 실행시킬 수 있습니다.

 

 

 

이벤트 핸들러와 이벤트 모델

이벤트 핸들러란?

 - 이벤트가 발생 했을 때 실행되는 함수 또는 코드 조각을 말합니다.

 - 자바스크립트에서 이벤트 핸들러는 HTML 요소에 직접 지정(인라인 방식) 하거나, 자바스크립트에서 할당하거나(전통적 방식), addEventListener 메서드를 사용(표준방식)하여 등록할 수 있습니다.

 

이벤트 모델

 - 여러 요소에 동일한 이벤트가 발생하였을 때 어떻게 처리되는지 정하는 규칙입니다.

 - 표준 방식에서는 addEventListener 메서드의 세 번째 인자로 이벤트 모델을 선택할 수 있습니다.

 

 

 

버블링과 캡처링

 - 인터넷 브라우저에서는 이벤트가 전파되는 방향에 따라 버블링(bubbling)과 캡처링(capturing)으로 구분됩니다. 버블링(bubbling)은 자식 요소에서 부모 요소로 이벤트가 전파되는 방식을 나타내며, 캡처링(capturing)은 부모 요소에서 자식 요소로 전파되는 방식을 나타냅니다.

 

  • 버블링(bubbling) : 이벤트가 발생한 요소부터 상위 요소로 순차적으로 전파되는 방식입니다. 예를 들어 div 요소를 클릭하면 div의 클릭 이벤트 핸들러가 실행되고, 그 다음 부모 요소인 body의 클릭 이벤트 핸들러가 실행됩니다.
  • 캡처링(capturing) : 이벤트가 발생한 요소부터 하위 요소로 순차적으로 전파되는 방식입니다. 예를 들어 div 요소를 클릭하면 먼저 body의 이벤트 핸들러가 실행되고, 그 다음 자식요소인 div의 클릭 이벤트 핸들러가 실행됩니다.
  • 버블링과 캡처링을 선택하기 위해서는 addEventListener메서드의 세 번째 인자로 true 또는 false를 전달하는 것입니다. (true - 캡처링, false - 버블링 (기본값은 false))
  • 버블링과 캡처링을 막는 방법은 event.stopPropagation 메서드를 호출하는 것입니다.

 

 

버블링(bubbling)

 

이벤트가 발생한 요소부터 상위 요소로 순차적으로 전파되는 방식입니다. 예를 들어 div 요소를 클릭하면 div의 클릭 이벤트 핸들러가 실행되고, 그 다음 부모 요소인 body의 클릭 이벤트 핸들러가 실행됩니다.

 

예시)

// HTML
<div class="div">
	<button class="button">Click me</button>
</div>
// JavaScript
const div = document.querySelector(".div");
const button = document.querySelector(".button");

div.addEventListener("click", () => {
console.log("div clicked");
});

button.addEventListener("click", () => {
console.log("button clicked");
});

 

버튼을 클릭하면 콘솔에 "button clicked"와 "div clicked"가 차례로 출력됩니다.

 

이처럼 버블링 현상이 일어나는 것을 방지하고 싶다면, event 객체의 stopPropagation 메서드를 사용할 수 있습니다.

 

예시)

// HTML
<div class="div">
	<button class="button">Click me</button>
</div>
// JavaScript
const div = document.querySelector(".div");
const button = document.querySelector(".button");

div.addEventListener("click", () => {
console.log("div clicked");
});

button.addEventListener("click", (event) => {
console.log("button clicked");
event.stopPropagation(); // 버블링 방지
});

 

 

이 코드를 실행하면 button을 클릭하면 콘솔에 "button clicked"만 출력되고 "div clicked"는 출력되지 않습니다. stopPropagation 메서드는 현재 요소에서만 이벤트 핸들러를 실행하고 부모 요소로 전파되는 것을 막습니다.

 

 

캡처링(capturing)

 이벤트가 발생한 요소부터 하위 요소로 순차적으로 전파되는 방식입니다. 예를 들어 div 요소를 클릭하면 먼저 body의 이벤트 핸들러가 실행되고, 그 다음 자식요소인 div의 클릭 이벤트 핸들러가 실행됩니다.

 

예시)

// HTML
<div class="div">
	<button class="button">Click me</button>
</div>
// JavaScript
const div = document.querySelector(".div");
const button = document.querySelector(".button");

div.addEventListener("click", () => {
console.log("div clicked");
}, true); // 캡처링 옵션 활성화

button.addEventListener("click", () => {
console.log("button clicked");
}, true); // 캡처링 옵션 활성화

버튼을 클릭하면 콘솔에 "div clicked"와 "button clicked"가 차례로 출력됩니다.

 

이처럼 캡처링 현상이 일어나는 것을 방지하고 싶다면, addEventListener 메서드의 세 번째 인자로 false를 전달 할 수 있습니다. 

 

예시)

// HTML
<div class="div">
	<button class="button">Click me</button>
</div>
// JavaScript
const div = document.querySelector(".div");
const button = document.querySelector(".button");

div.addEventListener("click", () => {
console.log("div clicked");
}, false); // 캡처링 옵션 비활성화

button.addEventListener("click", () => {
console.log("button clicked");
}, false); // 캡처링 옵션 비활성화

 

 

캡처링과 버블링의 유용한 상황

캡처링과 버블링은 이벤트가 발생한 노드를 찾기위해 DOM 트리를 탐색하는 방식입니다. 캡처링은 Document 루트에서부터 Target node 까지 내려가는 방식이고, 버블링은 Target node 부터 Document 루트 까지 올라오는 방식입니다.

 

장점

  • 캡처링은 이벤트가 발생하기 전에 어떤 작업을 수행하고 싶을 때 사용할 수 있습니다. 예를 들어, 부모 요소에 캡처링 단계에서 실행되는 이벤트 리스너를 등록하면 자식 요소에 발생한 이벤트를 가로채거나 수정할 수 있습니다.
  • 버블링은 이벤트 위임 패턴을 구현할 때 사용할 수 있습니다.  예를 들어, 여러 자식 요소에 공통된 이벤트 리스너를 부모 요소에 한 번만 등록하면 자식 요소에 발생한 이벤트가 부모 요소로 전달되면서 실행됩니다. (> 메모리와 성능 절약 가능)

 

 

 

이벤트 위임

이벤트 위임이란?

- 하위 요소마다 이벤트 리스너를 등록하지 않고 상위 요소에서 하위 요소의 이벤트를 제어하는 방식입니다.

 

장점

  • 메모리와 성능 절약(> 하위 요소가 많아도 상위 요소에 한 번만 이벤트 리스너를 등록하면 되기 때문)
  • 동적으로 추가되거나 삭제되는 하위 요소에도 이벤트가 적용(> 상위 요소에서 버블링된 이벤트를 감지하기 때문)

 

예시)

 

다음과 같은 HTML 코드가 있다고 가정해 보세요.

<ul id="menu">
	<li data-action="save">Save</li>
	<li data-action="load">Load</li>
	<li data-action="search">Search</li>
</ul>

이 코드에서는 각 li 요소에 data-action 속성을 사용하여 특정 행동을 지정했습니다. 이제 우리는 이벤트 위임을 사용하여 ul 요소에 클릭 이 벤트 핸들러를 추가하고, 클릭된 li 요소의 data-action 속성 값을 가져와서 해당하는 행동을 수행할 수 있습니다.

 

다음과 같은 JavaScript 코드를 보세요.

let menu = document.getElementById('menu');
menu.addEventListener('click', function(event) {
	let target = event.target; // 클릭된 요소
	let action = target.dataset.action; // data-action 속성 값
		if (action) {
			// action 값이 있으면 해당하는 행동 수행
			switch (action) {
			case 'save':
			// 저장 로직
			break;
			case 'load':
			// 불러오기 로직
			break;
			case 'search':
			// 검색 로직
			break;
		}
	}
});

이렇게 하면 우리는 각 li 요소에 개별적으로 이벤트 핸들러를 등록하지 않아도 되고, 새로운 li 요소를 추가해도 자동으로 동일한 로직이 적용됩니다

 

 

 

 

 

#출처 엘리스 AI 트랙 JavaScript 101 - (8) 이벤트의 버블링과 캡처링

Comments