Atomic Habits

addEventListener 함수 ‘false’ / 버블링 / 캡쳐링 / 이벤트 위임 본문

IT/HTML-CSS

addEventListener 함수 ‘false’ / 버블링 / 캡쳐링 / 이벤트 위임

체계성 2022. 5. 29. 07:39

 

https://joshua1988.github.io/web-development/javascript/event-propagation-delegation/#%EC%9D%B4%EB%B2%A4%ED%8A%B8-%EC%BA%A1%EC%B3%90---event-capture

 

이벤트 버블링, 이벤트 캡처 그리고 이벤트 위임까지

(기본) 이벤트 버블링, 이벤트 캡처링, 그리고 이벤트 위임까지 이벤트 전달 방식과 관련된 모든 것을 파헤쳐 봅니다.

joshua1988.github.io

 

이벤트 버블링(1)

three 클래스를 갖는 div 태그를 클릭했을 때의 결과

div 태그 한 개만 클릭했을 뿐인데 왜 3개의 이벤트가 발생되는 걸까요? 그 이유는 브라우저가 이벤트를 감지하는 방식 때문입니다.

 

브라우저는 특정 화면 요소에서 이벤트가 발생했을 때 그 이벤트를 최상위에 있는 화면 요소까지 이벤트를 전파시킵니다. 따라서, 클래스 명 three -> two -> one 순서로 div 태그에 등록된 이벤트들이 실행됩니다. 마찬가지로 two 클래스를 갖는 두 번째 태그를 클릭했다면 two -> one 순으로 클릭 이벤트가 동작하겠죠.

 

여기서 주의해야 할 점은 각 태그마다 이벤트가 등록되어 있기 때문에 상위 요소로 이벤트가 전달되는 것을 확인할 수 있습니다. 만약 이벤트가 특정 div 태그에만 달려 있다면 위와 같은 동작 결과는 확인할 수 없습니다.

 

이와 같은 하위에서 상위 요소로의 이벤트 전파 방식을 이벤트 버블링(Event Bubbling)이라고 합니다.
“Trigger clicks all the way up”

 

 

 이벤트 버블링(2)

화면의 모든 인풋 박스에 일일이 이벤트 리스너를 추가하는 대신 이제는 인풋 박스의 상위 요소인 ul 태그, .itemList에 이벤트 리스너를 달아놓고 하위에서 발생한 클릭 이벤트를 감지합니다. 이 부분이 앞에서 배웠던 이벤트 버블링이죠.

 

이젠 리스트 아이템을 새로 추가할 때마다 클릭 이벤트를 안 달아도 되겠네요 :)

참고 : 위 코드는 현재 인풋 박스의 이벤트만 다루는 것이 아니라 label 태그의 이벤트도 감지합니다. event 객체를 이용하여 인풋 박스의 이벤트만 감지할 수 있도록 구현하려면 ??

 

■ 이벤트 버블링 막기

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

위 API는 해당 이벤트가 전파되는 것을 막습니다. 따라서, 이벤트 버블링의 경우에는 클릭한 요소의 이벤트만 발생시키고 상위 요소로 이벤트를 전달하는 것을 방해합니다. 그리고 이벤트 캡쳐의 경우에는 클릭한 요소의 최상위 요소의 이벤트만 동작시키고 하위 요소들로 이벤트를 전달하지 않습니다.

 

 

 

 

 



 이벤트 위임 - Event Delegation
앞에서 살펴본 이벤트 버블링과 캡쳐는 사실 이벤트 위임을 위한 선수 지식이라고 해도 과언이 아닙니다. 이벤트 위임은 실제 바닐라 JS로 웹 앱을 구현할 때 자주 사용하게 되는 코딩 패턴입니다.

이벤트 위임을 한 문장으로 요약해보면 ‘하위 요소에 각각 이벤트를 붙이지 않고 상위 요소에서 하위 요소의 이벤트들을 제어하는 방식’입니다.

말보다는 코드죠. 아래 코드를 함께 살펴보겠습니다.

 

<h1>오늘의 할 일</h1>
<ul class="itemList">
<li>
<input type="checkbox" id="item1">
<label for="item1">이벤트 버블링 학습</label>
</li>
<li>
<input type="checkbox" id="item2">
<label for="item2">이벤트 캡쳐 학습</label>
</li>
</ul>


var inputs = document.querySelectorAll('input');
inputs.forEach(function(input) {
input.addEventListener('click', function(event) {
alert('clicked');
});
});


위 코드는 할 일 목록을 간단한 리스트 아이템으로 나타낸 코드입니다.


할 일 목록의 체크 박스를 클릭했을 때 클릭 이벤트 리스너가 동작하는 모습
자바스크립트 querySelectorAll()를 이용해 화면에 존재하는 모든 인풋 박스 요소를 가져온 다음 각 인풋 박스의 요소에 클릭 이벤트 리스너를 추가합니다. 화면을 실행시키고 각 리스트 아이템의 인풋 박스(체크 박스)를 클릭하면 위와 같이 경고 창이 표시되죠.

여기까지는 별다를 것 없는 이상하지 않은 코드였는데요. 그런데 만약 여기서 할 일이 더 생겨서 리스트 아이템을 추가하면 어떻게 될까요?

// ...

// 새 리스트 아이템을 추가하는 코드

var itemList = document.querySelector('.itemList');

var li = document.createElement('li');
var input = document.createElement('input');
var label = document.createElement('label');
var labelText = document.createTextNode('이벤트 위임 학습');

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

위 코드로 새로 추가한 리스트 아이템에 클릭 이벤트가 정상적으로 동작하지 않습니다.

새로 추가된 리스트 아이템에는 클릭 이벤트 리스너가 동작하지 않네요. 왜 그럴까요?

코드를 다시 살펴보면, 인풋 박스에 클릭 이벤트 리스너를 추가하는 시점에서 리스트 아이템은 두 개입니다. 따라서, 새롭게 추가된 리스트 아이템에는 클릭 이벤트 리스너가 등록되지 않았죠. 이런 식으로 매번 새롭게 추가된 리스트 아이템까지 클릭 이벤트 리스너를 일일이 달아줘야 할까요?

리스트 아이템이 많아지면 많아질수록 이벤트 리스너를 다는 작업 자체가 매우 번거롭습니다. 이 번거로운 작업을 해결할 수 있는 방법이 바로 이벤트 위임(Event Delegation)입니다.

앞에서 살펴본 코드를 아래와 같이 변경해보겠습니다.

// var inputs = document.querySelectorAll('input');
// inputs.forEach(function(input) {
//  input.addEventListener('click', function() {
//  alert('clicked');
//  });
// });

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

// 새 리스트 아이템을 추가하는 코드
// ...



화면의 모든 인풋 박스에 일일이 이벤트 리스너를 추가하는 대신 이제는 인풋 박스의 상위 요소인 ul 태그, .itemList에 이벤트 리스너를 달아놓고 하위에서 발생한 클릭 이벤트를 감지합니다. 이 부분이 앞에서 배웠던 이벤트 버블링이죠.

이젠 리스트 아이템을 새로 추가할 때마다 클릭 이벤트를 안 달아도 되겠네요 :)

참고 : 위 코드는 현재 인풋 박스의 이벤트만 다루는 것이 아니라 label 태그의 이벤트도 감지합니다. event 객체를 이용하여 인풋 박스의 이벤트만 감지할 수 있도록 구현해보세요.

 

이렇게 ???
const input = event.target.closest('input')
if ( ! input ) return 

 

 

 

 

http://daplus.net/javascript-%EC%9D%B4-%EA%B0%84%EB%8B%A8%ED%95%9C-addeventlistener-%ED%95%A8%EC%88%98-%EB%92%A4%EC%97%90-false%EA%B0%80-%EC%82%AC%EC%9A%A9%EB%90%98%EB%8A%94-%EC%9D%B4%EC%9C%A0%EB%8A%94-%EB%AC%B4/

 

[javascript] 이 간단한 addEventListener 함수 뒤에 'false'가 사용되는 이유는 무엇입니까? - 리뷰나라

끝에 대한 거짓은 무엇입니까? 감사. window.addEventListener('load', function() { alert("All done"); }, false); 답변 MDN Web Docs 에 따르면 세 번째 매개 변수는 다음과 같습니다. useCapture를 하는 경우는 true, useCaptur

daplus.net

 

 

 

 

Comments