무브라더

[JavaScript] 이벤트 버블링, 이벤트 캡쳐, 이벤트 위임, event.stopPropagation() 본문

Programming/JavaScript

[JavaScript] 이벤트 버블링, 이벤트 캡쳐, 이벤트 위임, event.stopPropagation()

동스다
반응형
SMALL

이벤트 버블링

특정 화면 요소에서 이벤트가 발생했을 때 해당 이벤트가 더 상위의 화면 요소들로 전달되어 가는 특성을 의미한다.

<body>
	<div class="one">
		<div class="two">
			<div class="three">
			</div>
		</div>
	</div>
</body>
const divs = document.querySelectorAll('div');
divs.forEach(function(div) {
	div.addEventListener('click', logEvent);
});

function logEvent(event) {
	console.log(event.currentTarget.className);
}

three 클릭 시 실행 결과값

 

div 태그 한개만 클릭했을 뿐인데도 3개의 이벤트가 발생하는걸 결과로 알 수 있다.

그 이유는 브라우저가 이벤트를 감지하는 방식 때문이다.

브라우저는 특정 화면 요소에서 이벤트가 일어났을 때 이벤트를 최상위에 있는 화면 요소까지 전파 시킨다.

 

주의해야할 점은 각 태그마다 이벤트가 등록되어 있기 때문에 상위 요소로 이벤트가 전달되는 것을 확인 할 수 있는데 만약 이벤트가 특정 div 태그에만 달려있다면 위 실행 결과 값 처럼 나오지는 않을 것이다.

 

 

 

이벤트 캡쳐

이벤트 버블링과 반대로 상위에서 하위요소로 내려간다.

이벤트 버블링과 비슷한 코드예제를 살펴보자.

<body>
	<div class="one">
		<div class="two">
			<div class="three">
			</div>
		</div>
	</div>
</body>
const divs = document.querySelectorAll('div');
divs.forEach(function(div) {
	div.addEventListener('click', logEvent, {
		capture: true // default 값은 false입니다.
	});
});

function logEvent(event) {
	console.log(event.currentTarget.className);
}

결과값

addEventListener() 에서 옵션 객체에 capture:true를 설정해주면 된다.

 

event.stopPropagation()

나는 하나의 부분만 이벤트가 실행되게 하고 싶다 라고 한다면 stopPropagation() 을 사용하면된다.

function logEvent(event) {
	event.stopPropagation();
}

해당 이벤트가 전파되는 것을 막는다. 즉 이벤트 버블링의 경우 상위 요소로 이벤트가 전달되는 것을 막고 이벤트 캡쳐의 경우 하위 요소로 이벤트가 전달되는 것을 막아준다.

 

 

이벤트 위임 

이벤트 버블링과 캡쳐는 사실 이벤트 위임을 위한 선수 지식이라고 할 수 있다.

이벤트 위임은 실제로 웹이나 앱을 구현할 때 자주 사용하게 되는 코딩패턴이다.

 

이벤트 위임이란 '하위 요소에 각각의 이벤트를 붙이지 않고 상위 요소에서 하위 요소의 이벤트를 제어하는 방식' 이다.

<h1>과일이 좋아</h1>
<ul class="fruitList">
	<li>
		<input type="checkbox" id="fruit1">
		<label for="fruit1">딸기</label>
	</li>
	<li>
		<input type="checkbox" id="fruit2">
		<label for="fruit2">바나나</label>
	</li>
</ul>
const fruits = document.querySelectorAll('input');
fruits.forEach(function(input) {
	input.addEventListener('click', function(event) {
		alert('clicked');
	});
});

자바스크립트 querySelectorAll()를 이용해 화면에 존재하는 모든 인풋 박스 요소를 가져온 다음 각 인풋 박스의 요소에 클릭 이벤트 리스너를 추가해준다. 여기까지는 다를바 없는 코드다.

 

하지만 만약 과일을 더 추가하고싶어서 js로 추가를 하는 코드를 만들어보면

 

const fruitList = document.querySelector('.fruitList');

const li = document.createElement('li');
const input = document.createElement('input');
const label = document.createElement('label');
const labelText = document.createTextNode('오렌지');

input.setAttribute('type', 'checkbox');
input.setAttribute('id', 'fruit3');
label.setAttribute('for', 'fruit3');
label.appendChild(labelText);
li.appendChild(input);
li.appendChild(label);
fruitList.appendChild(li);

 이렇게 추가해준 체크박스에는 이벤트가 동작하지 않을 것이다. 왜그럴까?

 

input 박스에 클릭 이벤트 리스너를 추가하는 시점에서 fruitList 안에 fruit는 두개 뿐이다.

따라서 새롭게 추가된 fruitList 에는 클릭이벤트 리스너가 등록되지 않았다.

그렇다면 매번 추가할때마다 이벤트를 하나하나 달아줘야하는 것일까?

 

만약 추가되는게 100개 200개 1000개가 되버린다면? 작업량이 어마어마해질 것이다.

 

이럴때 사용하는 것이 이벤트 위임이다.

// const fruits = document.querySelectorAll('input');
// fruits.forEach(function(input) {
// 	 input.addEventListener('click', function(event) {
//	 	 alert('clicked');
//	 });
// });

const fruitList = document.querySelector('.fruitList');
fruitList.addEventListener('click', function(event) {
	alert('clicked');
});

화면의 모든 input 박스에 하나하나 이벤트 리스너를 달아주는 대신 상위 ul 태그에 이벤트 리스너를 달아놓고 하위에서 발생한 클릭 이벤트를 감지한다. (이벤트 버블링)

반응형
LIST

'Programming > JavaScript' 카테고리의 다른 글

[JavaScript] async 와 await  (0) 2022.04.01
[JavaScript] Promise 에 대해서 알아보자  (0) 2022.04.01
[JavaScript] apply, call, bind  (0) 2022.03.29
[JavaScript] this 바인딩  (0) 2022.03.29
[JavaScript] Array.from  (0) 2022.03.25
Comments