[자바스크립트] 이벤트 버블링, 이벤트 캡쳐 그리고 이벤트 위임

minidoo·2020년 11월 9일
0

자바스크립트 / NodeJS

목록 보기
19/27
post-thumbnail

이벤트 버블링 (Event Bubbling)

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

<body>
  <div class="one">
    <div class="two">
      <div class="three">
      </div>
    </div>
  </div>
</body>
var divs = document.querySelectorAll('div');
divs.forEach(div => {
  div.addEventListener('click', (event) => {
    console.log(event.currentTarget.className);
  });
});

위의 코드에서 최하위 div 태그 <div class="three"></div>를 클릭하면

three
two
one

다음과 같은 결과가 실행된다.
브라우저는 특정 화면 요소에서 이벤트가 발생했을 때, 해당 이벤트 최상위에 있는 화면 요소까지 이벤트를 전파시킨다. 따라서 클래스 'three'를 클릭하면 three - two - one 순으로 이벤트가 전파되는 것이다.

이와 같이 하위에서 상위 요소로 이벤트가 전파되는 방식을 이벤트 버블링(Event Bubbling)이라 한다.

이벤트 캡쳐 (Event Capture)

특정 화면 요소에서 이벤트가 발생했을 때,
해당 이벤트의 최상위 태그에서 더 하위의 화면 요소들로 전달되어 가는 특성

<body>
  <div class="one">
    <div class="two">
      <div class="three">
      </div>
    </div>
  </div>
</body>
var divs = document.querySelectorAll('div');
divs.forEach(div => {
  div.addEventListener('click', (event) => {
    console.log(event.currentTarget.className);
  }, { capture: true });
});

이벤트 캡쳐는 addEventListener() 의 세 번째 옵션 값으로 capture: true 를 설정해준다.
default 값은 false 이기 때문에 true로 옵션을 설정해줘야 이벤트 캡쳐가 작동한다.

위의 코드에서 최하위 div 태그 <div class="three"></div>를 클릭하면

one
two
three

다음과 같은 결과가 실행된다.
클래스 three를 클릭했지만 이벤트 캡쳐에 의해서 최상위 태그인 body 태그에서 해당 태그를 찾아 내려간다. 따라서 body - one - two - three 순으로 상위에서 하위로 이벤트가 전파된다.

event.stopPropagation( )

이벤트 버블링, 캡쳐를 사용하지 않고 원하는 화면 요소의 이벤트만 작동시키기 위해 사용한다.
stopPropagation()을 사용하면 위의 코드 기준으로 <div class="three"></div> 을 클릭했을 때 three, one이 찍힐 것이다.


var divs = document.querySelectorAll('div');
divs.forEach(div => {
  div.addEventListener('click', (event) => {
    event.stopPropagation();
    console.log(event.currentTarget.className);   // three
  });
});
var divs = document.querySelectorAll('div');
divs.forEach(div => {
  div.addEventListener('click', (event) => {
    event.stopPropagation();
    console.log(event.currentTarget.className);   // one
  }, { capture: true });
});

이벤트 위임 (Event Delegation)

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

<h1>점심 추천 리스트</h1>
<ul class="lunchList">
  <li>
    <input type="checkbox" id="lunch1">
    <label for="lunch1">떡볶이</label>
  </li>
  <li>
    <input type="checkbox" id="lunch2">
    <label for="lunch2">짜파게티</label>
  </li>
</ul>
var inputs = document.querySelectorAll('input');
inputs.forEach(input => {
  input.addEventListener('click', (event) => {
    console.log('check!');
  })
});

위의 코드에서 각 아이템 체크 박스를 클릭할 때마다 'click!' 콘솔이 찍힌다.
그럼 여기서 자바스크립트 코드를 이용해 리스트 아이템을 추가해보자.

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

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', 'lunch3');
label.setAttribute('for', 'lunch3');
label.appendChild(labelText);
li.appendChild(input);
li.appendChild(label);
lunchList.appendChild(li);

새로 추가된 '삼겹살' 리스트에는 클릭 이벤트 리스너가 동작하지 않는다.
이유는 input 박스에 클릭 이벤트를 추가하는 시점에 리스트 아이템은 '떡볶이', '짜파게티' 2개이기 때문이다. 따라서 새롭게 추가된 리스트 아이템에는 클릭 이벤트 리스너가 등록되지 않았다.

리스트 아이템이 많아지면 각각의 아이템에 이벤트 리스너를 다는 것은 번거로울 것이다.
이벤트 위임을 사용하여 상위 요소에서 하위 요소의 이벤트를 제어하도록 한다.

var lunchList = document.querySelector('.lunchList');
lunchList.addEventListener('click', (event) => {	// Event Delegation
  console.log('check!');
});

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', 'lunch3');
label.setAttribute('for', 'lunch3');
label.appendChild(labelText);
li.appendChild(input);
li.appendChild(label);
lunchList.appendChild(li);

가장 상위 요소인 ul 태그에 이벤트 리스너를 달아놓으면 하위에서 발생한 클릭 이벤트를 감지한다.
이는 위에서 학습한 '이벤트 버블링'과 관련있다.


참고 사이트

https://joshua1988.github.io/web-development/javascript/event-propagation-delegation/

0개의 댓글