이벤트위임

lee jae hwan·2022년 8월 13일

브라우저

목록 보기
26/39

캡처링과 버블링을 활용하면 강력한 이벤트 핸들링 패턴인 이벤트 위임(event delegation)을 구현할 수 있다.

유사한 내용의 핸들러를 여러개의 요소노드마다 할당하는 것은 중복개념이므로 피할 수 있다면 피하는 것이 유지보수에 좋다.

상위요소에만 핸들러를 할당하여 하위요소들의 이벤트를 처리할 수 있다면 효율적이고 이러한 것을 이벤트위임이라 한다.

이벤트위임은 이벤트가 발생했을때 상위요소핸들러에서 event.target에 접근할 수 있기때문에 가능하다.

활용

div내에 저장하기, 불러오기, 검색하기 버튼이 있을때 보통 각각의 버튼에 핸들러를 할당하여 처리할 것이다.

이벤트위임을 알면 코드가 간결해지고 유지보수가 쉬워진다.

div에 클릭이벤트를 할당하고 event.target을 구분하여 처리한다.

let menu = document.querySelector("div");
menu?.addEventListener("click", fn);

function fn(event) {
   switch (event.target.dataset.action) {
      case "save":
         break;

      case "load":
         break;

      case "search":
         break;
   }
}

핸들러내에서 action을 switch문법으로 구분해서 처리가능하나 코드가 길어져 가독성이 떨어진다.

보다 진보된 방법이 필요하다.

class Menu{
  #menu;
  constructor(div){
    this.#menu = div;
    div.addEventListener('click', this.onclick.bind(this));
  }
  onclick(event){
    this[event.target.dataset.action](event);
  }
  save(event){
    console.log(event.target);
  }
  load(event){
    console.log(event.target);
  }
  search(event){
    console.log(event.target);
  }
}

new Menu(window['menu']);

핸들러를 class화하여 각 버튼의 핸들러를 객체메소드로 가지는 핸들러객체를 생성하면 가독성이 향상된다.

div.addEventListener('click', this.onclick.bind(this));로 div의 클릭이벤트를 핸들러객체의 클릭메소드로 할당할때 this를 바인딩하지 않으면 객체핸들러내의 this가 div가 되기때문에 바인딩해야 한다.

이 방법을 사용하면 버튼이 추가되어도 핸들러객체의 메소드만 추가하면 되므로 유연성이 좋아진다.



행동패턴

<input type="button" value="1" data-counter>
<input type="button" value="2" data-counter>

document.addEventListener('click', function(event) {

    if (event.target.dataset.counter != undefined) { // 속성이 존재할 경우
      event.target.value++;
    }

  });

이벤트가 발생해야할 요소노드들에 커스텀속성을 넣은후 상위요소에 핸들러를 할당한후 이벤트가 발생할때마다 event.target.dataset.counter프로퍼티값을 검사하여 처리한다.

document객체에 핸들러를 할당할 때는 document.onclick를 사용해선 안된다. 충돌가능성때문에 반드시 document.addEventListener메소드를 사용하는것이 안전하다.

토글러보여주기

<button data-toggle-id="subscribe-mail">
  구독 폼 보여주기
</button>

<form id="subscribe-mail" hidden>
  메일 주소: <input type="email">
</form>

<script>
  document.addEventListener('click', function(event) {
    let id = event.target.dataset.toggleId;
    if (!id) return;

    let elem = document.getElementById(id);

    elem.hidden = !elem.hidden;
  });
</script>

여러개의 버튼들로 컨텐츠를 보여주고 숨길때 버튼마다 이벤트를 할당하지 않고 버튼에 커스텀속성을 추가하고 상위요소에서 이벤트처리시 커스텀속성값으로 처리하는것이 좋다.

0개의 댓글