기본으로 돌아가기: 이벤트 위임



Back to basics is a series of small posts where I explain basic, dependency free web techniques I keep using in my projects. These aren't revelations but helped me over the years to build sturdy, easy to maintain projects.



웹 인터페이스 구축과 관련하여 제가 가장 좋아하는 트릭 중 하나는 이벤트 위임입니다.

이벤트는 적용한 요소에서만 발생하지 않습니다. 대신 DOM 트리에서 이벤트까지 내려가 다시 백업합니다. 이벤트 수명 주기의 이러한 단계를 event bubbling and event capture 이라고 합니다.

이것의 실질적인 결론은 문서의 모든 요소에 이벤트 핸들러를 적용할 필요가 없다는 것입니다. 대신 종종 부모 요소에 대한 하나의 처리기로 충분합니다. 오래 전에는 구형 브라우저에서 종종 이벤트 처리와 관련된 메모리 누수가 발생했기 때문에 이는 매우 중요했습니다.

링크 목록이 있고 이러한 링크를 따라가는 대신 사용자가 링크를 클릭할 때 코드에서 작업을 수행하려고 한다고 가정해 보겠습니다.

<ul id="dogs">
  <li><a href="#dog1">Dog1</a></li>
  <li><a href="#dog2">Dog2</a></li>
  <li><a href="#dog3">Dog3</a></li>
  <li><a href="#dog4">Dog4</a></li>
  <li><a href="#dog5">Dog5</a></li>
  <li><a href="#dog6">Dog6</a></li>
  <li><a href="#dog7">Dog7</a></li>
  <li><a href="#dog8">Dog8</a></li>
  <li><a href="#dog9">Dog9</a></li>
  <li><a href="#dog10">Dog10</a></li>
</ul>


각 링크를 반복하고 각각에 클릭 핸들러를 할당할 수 있습니다.

const linkclicked = (e,l) => {
  console.log(l);
  output.innerHTML = l.innerHTML; 
  e.preventDefault();
};
const assignhandlers = elm => {
  let links = document.querySelectorAll(`${elm} a`);
  links.forEach(l => {
    l.addEventListener('click', e => {linkclicked(e,l)});
  });
}
assignhandlers('#dogs');


try this event handling example here 코드는 GitHub( event.handling.html )에서 사용할 수 있습니다.

이것은 작동하지만 두 가지 문제가 있습니다.
  • 목록의 내용이 변경되면 목록을 다시 인덱싱해야 합니다(예: assignhandlers()를 한 번 더 호출)
  • 링크를 클릭하는 경우에만 반응합니다. 목록 항목을 클릭할 때 무언가를 수행하려면 핸들러를 더 많이 할당해야 합니다.

  • 예제에서 "Toggle more dogs"버튼을 클릭하여 시도할 수 있습니다. 목록에 더 많은 항목을 추가하고 항목을 클릭해도 아무 일도 일어나지 않습니다.

    이벤트 위임을 사용하면 훨씬 쉽습니다.

    document.querySelector('#dogs').
      addEventListener('click', e => {
        // What was clicked?
        let t = e.target; 
        // does it have an href?
        if (t.href) { 
          console.log(t.innerText); // f.e. "Dog5"  
          output.innerHTML = t.innerText; 
        }
        // if the list item was clicked
        if (t.nodeName === 'LI') { 
          // print out the link
          console.log(t.innerHTML);
          output.innerHTML = t.innerHTML; 
        }
      e.preventDefault(); // Don't follow the links
    });
    


    try this event delegation example here 코드는 GitHub( event-delegation.html )에서 사용할 수 있습니다. 이제 "Toggle more dogs"버튼을 클릭하고 강아지가 있는 링크를 클릭하면 여전히 작동하는 것을 볼 수 있습니다.

    클릭 이벤트가 발생한 요소를 확인하기 위해 수행할 수 있는 몇 가지 작업이 있습니다. 여기서 가장 중요한 비트는 let t = e.target; 행으로, 현재 이벤트 캡처/버블링 주기에 의해 보고된 요소를 저장합니다. 링크에 반응하려면 대상에 href가 있는지 확인합니다. 목록 항목에 반응하고 싶다면 nodeNameLI 와 비교합니다. 이러한 종류의 검사를 수행하는 경우 노드 이름은 항상 대문자입니다.

    훨씬 더 많은 유연성을 제공하고 콘텐츠 변경에 대해 걱정할 필요가 없기 때문에 이벤트 위임을 정말 좋아합니다. 핸들러는 필요할 때까지 대기합니다.

    좋은 웹페이지 즐겨찾기