Event Delegation(이벤트 위임)

LOOPY·2022년 2월 21일
0

기술면접준비

목록 보기
11/15
post-thumbnail

이벤트 위임

  • 비슷한 방식으로 여러 요소들을 다뤄야 할 때 사용
    (요소마다 핸들러를 할당하지 않고, 요소의 공통 조상에 이벤트 핸들러를 단 하나만 할당해도 여러 요소를 한꺼번에 다룰 수 있음)

1. 예시

<table>
  <tr>
    <th colspan="3"><em>A</em></th>
  </tr>
  <tr>
    <td class="a1"><strong>A1</strong>
      <br>A11<br>A12<br>A13</td>
    <td class="a2">...
    </td>
    <td class="a3">...</td>
  </tr>
  <tr>...2 more lines of this kind...</tr>
  <tr>...2 more lines of this kind...</tr>
</table>

<td>를 클릭했을 때, 그 칸을 강조하려면: 각<td>마다 onClick 핸들러를 할당하는 대신, 모든 이벤트를 잡아내는 핸들러를 <table>요소에 할당 (event.taget으로 어떤 요소가 클릭되었는지 감지하고 해당 칸을 강조하는 방식)

let selectedTd;

table.onclick = function(event) {
  let target = event.target; // 클릭이 어디서 발생한지 저장

  if (target.tagName != 'TD') return; // TD에서 발생한 게 아니라면 아무 작업도 하지 않음

  highlight(target); // 강조 
};

function highlight(td) {
  if (selectedTd) { // 이미 강조되어있는 칸이 있다면 원상태로 
    selectedTd.classList.remove('highlight');
  }
  selectedTd = td;
  selectedTd.classList.add('highlight'); // 새로운 td를 강조
}

table.onClick핸들러에서 event.target을 이용해 클릭 이벤트가 <td>안쪽에서 일어났는지도 구분하려면

table.onclick = function(event) {
  let td = event.target.closest('td'); // 가장 가까운 조상의 <td>요소 검색

  if (!td) return; // event.target이 <td> 안에 있지 않으면 종료

  if (!table.contains(td)) return; // 중첩 테이블이 있는 경우, 현재 테이블 내에 있지 않으면 종료

  highlight(td);
};

2. 활용

버튼이 있는 메뉴를 구현할 때, 각 버튼의 기능과 관련된 메서드가 있는 객체를 이미 구현했다면, (버튼 각각에 독립된 핸들러를 할당하는 방식이 아닌) 메뉴 전체에 핸들러를 하나 추가해주고 각 버튼의 data-action 속성에 호출할 메서드를 할당해주기

<div id="menu">
  <button data-action="save">저장하기</button>
  <button data-action="load">불러오기</button>
  <button data-action="search">검색하기</button>
</div>

<script>
  class Menu {
    constructor(elem) {
      this._elem = elem;
      elem.onclick = this.onClick.bind(this); // this에 바인딩 해 Menu 객체를 참조
    }

    save() {
      alert('저장하기');
    }

    load() {
      alert('불러오기');
    }

    search() {
      alert('검색하기');
    }

    onClick(event) {
      let action = event.target.dataset.action;
      if (action) {
        this[action]();
      }
    };
  }

  new Menu(menu);
</script>

-> 버튼마다 핸들러를 할당해주는 코드를 작성할 필요가 없고, 메서드를 만들고 HTML에 그 메서드를 써주기만 하면 됨 / 언제든지 버튼을 추가하고 제거할 수 있어 HTML 구조 유연

3. 요약

  • 1) 컨테이너에 하나의 핸들러 할당
    2) 핸들러의 event.target 사용해 이벤트가 발생한 요소가 어디인지 파악
    3) 원하는 요소에서 이벤트가 발생했다고 확인되면 이벤트 핸들링
  • 장점
    • 많은 핸들러를 할당하지 않아 초기화가 단순해지고 메모리 절약
    • 요소 추가 또는 제거 시 해당 요소에 할당된 핸들러를 추가 또는 제거할 필요가 없어 코드 간소화
    • innerHTML이나 유사 기능 스크립트로 요소 덩어리를 더하거나 뺄 수 있어 DOM 수정 쉬워짐
  • 단점
    • 반드시 이벤트가 버블링 되어야 함
    • 컨테이너에 할당된 핸들러가 응답할 필요가 있는 이벤트든 아니든 상관없이 모든 하위 컨테이너에서 발생하는 이벤트에 응답해야하므로 CPU 작업 부하 증가(무시할만한 수준)

참고자료
https://ko.javascript.info/event-delegation

profile
2년차 프론트엔드 개발자의 소소한 기록을 담습니다 :-)

0개의 댓글

관련 채용 정보