본문 바로가기

JavaScript/javascript 활용하기

이벤트 위임 처리하기

반응형
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <style>
      .event-container {
        border: 1px solid black;
        height: 40vh;
        width: 80vh;
        display: flex;
        perspective: 1000px;
      }
      .event {
        flex: 1;
        background: skyblue;
        color: white;
        font-size: 2rem;
        transition: all 2s;
      }
      .event:hover {
        transform: rotateY(45deg);
        background: blue;
      }
    </style>
  </head>
  <body>
    <div class="event-container">
      <button class="event" data-id="1">
        <span class="event-button-type">버튼</span
        ><span class="event-button-number">1</span>
      </button>
      <button class="event" data-id="2">
        <span class="event-button-type">버튼</span
        ><span class="event-button-number">2</span>
      </button>
      <button class="event" data-id="3">
        <span class="event-button-type">버튼</span
        ><span class="event-button-number">3</span>
      </button>
    </div>
    <script>
      (function () {
        const eventContainer = document.querySelector(".event-container");
        eventContainer.addEventListener("click", function (e) {
          console.log(e.target);
        });
      })();
    </script>
  </body>
</html>

 

위의 코드를 확인해보면 eventContainer 하나에만 event를 줬음에도 불구하고 e.target이라는 속성을 통해 클릭된 현재 객체에 대해 정보를 가져오는것을 확인할 수 있다. 이를 이벤트 위임이라고 한다.

 

addEventListener의 수가 늘어갈수록 브라우저의 속도가 느려질수 있기때문에 이벤트위임을 잘 활용하는것이 중요하다.

 

 

 

여기서 우리는 각 버튼을 클릭할때마다 button에 있는 data-id를 가져오려고한다. 

 

<script>
      (function () {
        const eventContainer = document.querySelector(".event-container");
        eventContainer.addEventListener("click", function (e) {
          console.log(e.target.dataset);
        });
      })();
    </script>

 

 

 

위와같이 버튼 전체를 클릭하는 경우에는 dataset이 나타나게 되어있지만 버튼이나 1, 2, 3 등의 span태그 내부를 누르는경우 정상적으로 dataset 을 가져올 수 없게된다.

 

이를 해결하는 방법이 두가지 있는데 첫번째는 css로 해결하는 방법이다. 

 

pointer-events

pointer-events 를 none으로 선택하게되면 해당 속성은 이벤트가 전파되어 가지 않는다. 

 .event-button-type,.event-button-number{
          pointer-events: none;
      }

 

정상 동작

두번쨰는 자바스크립트 방식이 있다. 

 

 

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <style>
      .event-container {
        padding:20px;
        border: 1px solid black;
        height: 40vh;
        width: 80vh;
        display: flex;
        perspective: 1000px;
      }
      .event {
        flex: 1;
        background: skyblue;
        color: white;
        font-size: 2rem;
        transition: all 2s;
      }
      .event:hover {
        transform: rotateY(45deg);
        background: blue;
      }
      /* .event-button-type,.event-button-number{
          pointer-events: none;
      } */
    </style>
  </head>
  <body>
    <div class="event-container">
      <button class="event" data-id="1">
        <span class="event-button-type">버튼</span
        ><span class="event-button-number">1</span>
      </button>
      <button class="event" data-id="2">
        <span class="event-button-type">버튼</span
        ><span class="event-button-number">2</span>
      </button>
      <button class="event" data-id="3">
        <span class="event-button-type">버튼</span
        ><span class="event-button-number">3</span>
      </button>
    </div>
    <script>
      (function () {
        const eventContainer = document.querySelector(".event-container");
        eventContainer.addEventListener("click", function (e) {
            let element = event.target;
            while(!element.classList.contains('event')){
                element = element.parentNode;
                if(element.nodeName === 'BODY'){
                    element = null;
                    return;
                }
            }
            console.log(element.dataset);
          
        });
      })();
    </script>
  </body>
</html>

 

 

while을 활용해서 해당 클릭한 요소가 datasets을 가지고있지 않으면 element 요소를 부모로 확장하는 방식이다. 

다만 body까지 올라간 경우에는 해당 요소가 존재하지 않기때문에 if 분기로 return 처리해준다. 

 

 

 

정상 동작 

 

반응형