[Deep Dive] 40. 이벤트(2)

김현주·2022년 7월 27일
0

Deep Dive

목록 보기
10/10
post-thumbnail

6. 이벤트 전파(event propagation)

<body>
  <ul id="fruits">
    <li id="apple">Apple</li>
    <li id="banana">Banana</li>
    <li id="orange">Orange</li>
  </ul>
  <script>
    const $fruits = document.getElementById("fruits");
    
    // #friuts 요소의 하위 요소인 li 요소를 클릭한 경우
    $fruits.addEventListener('click', e => {
      console.log(`이벤트 단계: ${e.eventPhase}`); // 3 : 이벤트 단계
      console.log(`이벤트 타깃: ${e.target}`); // {object HTMLLIElement}
      console.log(`커런트 타깃: ${e.currentTarget}`); // [object HTMLUListElement]
    });
  </script>
</body>
  • ul 요소의 두 번째 자식 요소인 li요소를 클릭하면 클릭 이벤트가 발생한다.
  • 생성된 이벤트 객체는 이벤트를 발생시킨 DOM 요소인 이벤트 타켓(event target)을 중심으로 DOM 트리를 통해 전파된다.
  • 이벤트 전파는 3단계로 구분
    ① 캡처링 단계(capturing phase) : 이벤트가 상위 요소에서 하위 요소 방향으로 전파
    ② 타깃 단계(target phase) : 이벤트가 이벤트 타깃에 도달
    ③ 버블링 단계(bubbling phase) : 이벤트가 하위 요소에서 상위 요소 방향으로 전파

7. 이벤트 위임

  • 이벤트 위임(event delegation) : 여러 개의 하위 DOM 요소에 각각 이벤트 핸들러를 등록하는 대신 하나의 상위 DOM 요소에 이벤트 핸들러를 등록하는 방법
  • 이벤트 위임을 통해 상위 DOM 요소에 이벤트 핸들러를 등록하면 여러 개의 하위 DOM 요소에 이벤트 핸들러를 등록할 필요가 없다.
<head>
  <style>
    #fruits {
      display: flex;
      list-style-type: none;
      padding: 0;
    }
    #fruits li {
      width: 100px;
      cursor: pointer;
    }
    #fruits .active {
      color: red;
      text-decoration: underline;
    }
  </style>
</head>
<body>
  <nav>
    <ul id="fruits">
      <li id="apple" class="active">Apple</li>
      <li id="banana">Banana</li>
      <li id="orange">Orange</li>
    </ul>
  </nav>
  <div>선택된 내비게이션 아이템: <em class="msg">apple</em></div>
  <script>
    const $fruits = document.getElementById("fruits");
    const $msg = document.querySelector(".msg");
    
    function activate({ target }){
      // 이벤트를 발생시킨 요소(target)가 ul#fruits의 자식 요소가 아니라면 무시
      if(!target.matches('#fruits > li')) return;
      
      [...$fruits.children].forEach($fruits => {
        $fruits.classList.toggle('active', $fruit === target);
        $msg.textContent = target.id;
      });
    }
    
    // 이벤트 위임 : 상위 요소(ul#fruits)는 하위 요소의 이벤트를 캐치할 수 있다.
    $fruits.onclick = activate;
  </script>
</body>

8. DOM 요소의 기본 동작 조작

① DOM 요소의 기본 동작 중단

  • 이벤트 객체의 preventDefault 메서드 DOM 요소의 기본 동작을 중단시킨다.
<body>
  <a href="https://www.google.com">GO!</a>
  <input type="checkbox">
  <script>
    document.querySelector('a').onclick = e => {
      // a 요소의 기본 동작을 중단
      e.preventDefault();
    };
    
    document.querySelector('input[type=checkbox]').onclick = e => {
      // checkbox 요소의 기본 동작을 중단
      e.preventDefault();
    };
  </script>
</body>

② 이벤트 전파 방지

  • 이벤트 객체의 stopPropagation 메서드는 하위 DOM 요소의 이벤트를 개별적으로 처리하기 위해 이벤트 전파를 중단시킨다.
<body>
  <div class="container">
    <button class="btn1">Button 1</button>
    <button class="btn2">Button 2</button>
    <button class="btn3">Button 3</button>
  </div>
  <script>
    // container 요소에 이벤트 위임 : 클릭된 하위 버튼 요소의 color를 변경
    document.querySelector(".container").onclick = ({ target }) => {
      if (!target.matches(".container > button")) return;
      target.style.color = "red";
    };
    
    // .btn2 요소는 이벤트를 전파하지 않으므로 상위 요소에서 이벤트를 캐치할 수 없다.
    document.querySelector(".btn2").onclick = e => {
      e.stopPropagation(); // 이벤트 전파 중단
    e.target.styled.color = "blue";
    }
  </script>
</body>
  • 하위 요소 중에서 btn2 요소는 자체적으로 이벤트를 처리한다.
  • btn2 요소는 자신이 발생시킨 이벤트가 전파되는 것을 중단하여 자신에게 바인딩된 이벤트 핸들러만 실행되도록 한다.

9. 이벤트 핸들러 내부의 this

① 이벤트 핸들러 어트리뷰트 방식

<body>
  <button onclick="handleClick()">Click me!</button>
  <script>
    // * 함수 내부의 this는 전역 객체 window를 가리킨다.
    function handleClick(button){
      console.log(button); // 이벤트를 바인딩한 button 요소
      console.log(this); // window
    }
  </script>
</body>

② 이벤트 핸들러 프로퍼티 방식과 addEventListener 메서드 방식

profile
✨프론트엔드 개발자가 되기 위한 독학러✨

0개의 댓글