이벤트 버블링

노성호·2021년 6월 23일
0

이벤트 버블링 예제

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <style>
      body {
        height: 100vh;
      }
      details {
        position: relative;
        margin: 0;
      }
      summary {
        padding: 10px;
        outline: 0;
        list-style: none;
      }
      details p {
        position: absolute;
        background-color: #fff;
        border: 1px solid black;
        top: calc(100% - 10px);
        right: 10px;
        width: 60%;
        padding: 10px;
        margin: 0;
        display: none;
        z-index: 1;
      }
      details.open p {
        display: block;
      }
    </style>
  </head>
  <body>
    <div id="wrapper">
      <details open>
        <summary>hello1</summary>
        <p>world1</p>
      </details>
      <details open>
        <summary>hello2</summary>
        <p>world2</p>
      </details>
      <details open>
        <summary>hello3</summary>
        <p>world3</p>
      </details>
      <details open>
        <summary>hello4</summary>
        <p>world4</p>
      </details>
      <details open>
        <summary>hello5</summary>
        <p>world5</p>
      </details>
    </div>
    <script>
      const $wrapper = document.getElementById("wrapper");
      const $details = document.querySelectorAll("details");
      document.body.addEventListener("click", (e) => {
        $details.forEach((elem) => elem.classList.remove("open"));
      });
      $wrapper.addEventListener("click", (e) => {
        e.preventDefault();
        e.stopPropagation();
        const $target = e.target;
        $target.parentNode.classList.add("open");
      });
    </script>
  </body>
</html>

e.stopPropagation() 메서드로 이벤트 버블링 방지 가능.

  1. body를 클릭시 모든 detail 태그의 open class를 지우는 이벤트 리스너 등록
  2. wrapper 이벤트 리스너에 event.stopPropagation() 함수 등록
  3. body 클릭시 디테일을 감추는 이벤트까지 올라가는 버블링 방지됨

정리를 더 하자면...
바디 클릭이벤트에 모든 디테일 태그의 class="open" 제거 로직을 심어놓는다. 이건 바디에 심어져있기 때문에 기존의 detail에서 작동해야 하는 p태그가 보여지지 않는다. 사실 한번 렌더링 되는데, 바디는 모든 영역에 존재하기 때문에 다시 open 클래스가 사라지고 다시 렌더링 되는것.
이벤트에 등록된 로직은 상위에 이벤트가 없다면 계속 부모 태그로 타고 올라간다고 함. 그래서 wrapper의 이벤트에 stopPropagation이라는 메서드를 등록해서 이벤트의 버블링을 막게된다.
내가 써놓고도 무슨말인지 모르겠지만... 하여튼 이벤트 버블링 개념을 이해하게 해준 간단한 예시코드.

0개의 댓글