Web/Frontend

Event Delegtion - 등록, 버블링, 멈추기

WakaraNai 2021. 5. 25. 20:53
728x90
반응형

이벤트 등록을 하는 경우

각각의 항목에 클릭 시 특정 이벤트가 발생해야 할 때

addEventListner로 이벤트 등록

 

 

 

예1) 4개의 li 태그에 이벤트 등록하기

<ul>
  <li>
    <img src="https://images-na.,,,,,/513hgbYgL._AC_SY400_.jpg" class="product-image" >    </li>
  <li>
    <img src="https://images-n,,,,,/41HoczB2L._AC_SY400_.jpg" class="product-image" >    </li>
  <li>
    <img src="https://images-na.,,,,51AEisFiL._AC_SY400_.jpg" class="product-image" >  </li>
 <li>
    <img src="https://images-na,,,,/51JVpV3ZL._AC_SY400_.jpg" class="product-image" >
 </li>
</ul>

 

var log = document.querySelector(".log");
var lists = document.querySelectorAll("ul > li");

for(var i=0,len=lists.length; i < len; i++) {
  lists[i].addEventListener("click", function(evt) {
     log.innerHTML = "clicked" + evt.currentTarget.firstElementChild.src;
  });
}

 

 

만약 동적으로 새로운 li 태그가 추가된다면?

추가된 엘리먼트에도 이벤트를 등록해주어야 함

 

 

 

버블링

클릭한 지점이 하위 엘리먼트여도, 그것을 감싸는 상위 엘리먼트까지 훑어보며

이벤트 리스너가 있는지 찾는 과정

 

만약 img, li, ul 각각 이벤트 등록했다면, 3개의 이벤트 리스너가 실행됨

아래 이미지는 하위 엘리먼트가 3번부터 이벤트가 발생하고, 2, 1 순으로 일어남을 보여줌

하위의 하나만 실행되는 것이 아님.

클릭 지점부터 가장 바깥쪽 엘리먼트까지 순차적으로 이벤트 리스너가 실행되는 것

 

+) Capturing : 이와 반대의 순서로 이벤트 발생

addEventListener 3번째 인자값에 true를 넣어줌

기본적으로는 Bubbling 순서로 이벤트 발생

예제)

https://codepen.io/je_ss2/pen/jOOOYEg

 

 

event.target

부모 요소의 핸들러는 이벤트가 정확히 어디서 발생했는지 등의 정보를 얻을 수 있음.

이벤트가 발생한 가장 안쪽의 요소는 target이라 부르고, event.target으로 접근.

 

  • event. target : 실제 이벤트가 시작된 'target' 요소. 버블링이 진행되어도 변하지 않음
  • this (=event.currentTarget) : '현재' 요소. 현재 실행 중인 핸들러가 할당된 요소를 참조함

가장 바깥쪽 엘리먼트를 클릭하면 target == currentTarget

 

참고

https://ko.javascript.info/bubbling-and-capturing

 

 

Event Delegation

예제 코드를 보면,

이미지만 아니라, 그 이미지만 담고있는 li를 클릭해도 

해당 이미지의 정보가 뜨게 하려면

버블링과 target을 이용해야 함.

동적으로 추가되는 li에도 적용되는 코드가 됨. 

 

즉 이미지 태그에 발생해야 될 이벤트를 위쪽 부모(li)에 위임했음.

자식 노드에 각각 이벤트 등록을 하지 않고도 효율적으로 이벤트를 등록할 수 있음

정리하자면, img 태그에 적용될 내용이, li에도 적용되게 하였고, 이 모든 내용이 둘을 포함하는 ul 태그에

이벤트를 등록하여 처리할 수 있음

var ul = document.querySelector("ul");
ul.addEventListener("click",function(evt) {
  debugger;
  // target이 image이면 src를 추출하기
    if(evt.target.tagName === "IMG") {
      log.innerHTML = "clicked" + evt.target.src;
  // target이 li이어도 src가 추출될 수 있도록 만들기 !!
    } else if (evt.target.tagName === "LI") {
      log.innerHTML = "clicked" + evt.target.firstElementChild.src;
    }
});

 

 

 

 

버블링 , 캡쳐링 예제

참고

https://jess2.xyz/JavaScript/bubbling-capturing/

https://codepen.io/je_ss2/pen/eYYYewp

 

eYYYewp

...

codepen.io

  • p태그 클릭 : p -> div -> form순서로 알림창이 뜬다.
  • div태그를 클릭 : div -> form순서로 알림창이 뜬다.

 

 

 

 

event.stopPropagation() - 버블링 멈추기

 

이벤트가 다른 엘리먼트로 전파되는 것을 원하지 않을 때 사용

아래 코드에 대해 p 태그를 클릭해도 버블링의 이벤트가 발생하지 않음

<form onclick="alert('form')">
  FORM
  <div onclick="alert('div')">
    DIV
    <p onclick="event.stopPropagation()">P</p>
  </div>
</form>

 

어떠한 태그를 클릭해도 이벤트 버블링이 발생하지 않게 하는 코드

for (let elem of document.querySelectorAll('*')) {
    elem.addEventListener("click", e => alertEvent(e, elem.tagName));
}

function alertEvent(event, _tagName) {
	event.stopPropagation();
	alert(_tagName);
}

https://codepen.io/je_ss2/pen/yLLLpyy

728x90
반응형

'Web > Frontend' 카테고리의 다른 글

Tab UI Component  (0) 2021.06.11
[CSS] float  (0) 2021.05.27
디렉토리 구성 방식 - JS&CSS  (0) 2021.05.24
웹 애니메이션 - requestAnimation, transition  (0) 2021.05.23
AJAX - 개발자도구의 Network 탭  (0) 2021.05.21