이벤트 위임 & 버블링

gang_shik·2025년 3월 27일
0

실습 회고록

목록 보기
10/10

이벤트 위임과 이벤트 버블링 정리


1. 이벤트 위임 (Event Delegation)

개념

  • 이벤트 위임은 부모 요소에 단일 이벤트 리스너를 추가하여 자식 요소의 이벤트를 처리하는 방식.
  • 이벤트 버블링을 활용하여 자식 요소에서 발생한 이벤트가 부모 요소로 전파되도록 함.

장점

  1. 성능 최적화:
    • 많은 자식 요소에 각각 이벤트 리스너를 추가할 필요 없이 부모에 단일 리스너만 추가하면 됨.
  2. 동적 요소 지원:
    • DOM에 새로 추가된 자식 요소도 부모의 이벤트 리스너로 처리할 수 있음.

단점

  1. 추가 조건 필요:
    • 이벤트가 버블링되므로, 특정 자식 요소만 처리하려면 조건문(if (event.target.tagName === 'I'))을 추가해야 함.
  2. 복잡성 증가:
    • 단순한 구조에서는 개별 리스너를 사용하는 것이 더 직관적일 수 있음.

2. 이벤트 버블링 (Event Bubbling)

개념

  • DOM 이벤트 모델에서, 이벤트가 발생하면 가장 안쪽의 요소(타겟)에서 시작하여 부모 요소로 전파됨.
  • 예를 들어, 자식 요소에서 click 이벤트가 발생하면 해당 이벤트는 부모, 조부모 등 상위 요소로 전달됨.

이벤트 캡처와의 차이

  • 캡처(Capturing): 이벤트가 최상위 요소에서 시작하여 타겟 요소로 전파됨.
  • 버블링(Bubbling): 타겟 요소에서 시작하여 최상위 요소로 전파됨.

3. mouseenter vs mouseover

특성mouseentermouseover
버블링버블링되지 않음버블링됨
트리거 조건자신만 트리거자신과 자식 모두 트리거
사용 사례자식 요소 무시자식 포함 처리
  • mouseenter: 마우스가 해당 요소에 진입할 때만 트리거되며, 자식 요소에는 영향을 받지 않음.
  • mouseover: 마우스가 해당 요소 또는 그 자식 요소에 진입할 때마다 트리거됨.

장단점 비교

  • mouseenter:
    • 버블링되지 않으므로 불필요한 이벤트 트리거를 방지할 수 있음.
    • 자식 요소가 없는 구조에서 효율적임.
  • mouseover:
    • 버블링되므로 부모 컨테이너에서 자식 요소의 이벤트를 감지할 수 있음.
    • 이벤트 위임 방식에 적합함.

4. mouseleave vs mouseout

특성mouseleavemouseout
버블링버블링되지 않음버블링됨
트리거 조건자신만 트리거자신과 자식 모두 트리거
사용 사례자식 요소 무시자식 포함 처리
  • mouseleave: 마우스가 해당 요소 전체에서 벗어날 때만 트리거되며, 자식 요소에는 영향을 받지 않음.
  • mouseout: 마우스가 해당 요소 또는 그 자식 요소에서 벗어날 때마다 트리거됨.

장단점 비교

  • mouseleave:
    • 버블링되지 않으므로 불필요한 이벤트 트리거를 방지할 수 있음.
    • 자식 요소가 없는 구조에서 효율적.
  • mouseout:
    • 버블링되므로 부모 컨테이너에서 자식 요소의 이벤트를 감지할 수 있음.
    • 이벤트 위임 방식에 적합함.

코드 비교 및 분석

원래 코드 (개별 리스너 + mouseenter, mouseleave)

stars.forEach((star) => {
  star.addEventListener('mouseenter', handleMouseEnter);
  star.addEventListener('mouseleave', handleMouseLeave);
  star.addEventListener('click', handleClick);
});
  • 각 별(i) 태그에 개별적으로 리스너를 추가.
  • 이 방식은 구조가 단순하고 코드 가독성이 높음.
  • 별점 개수가 많아질 경우 성능 저하 가능성이 있음.

중간 코드 (이벤트 위임 + mouseover, mouseout)

container.addEventListener('mouseover', (event) => {
  if (event.target.tagName === 'I') {
    const ratingValue = parseInt(event.target.dataset.ratingValue, 10);
    stars.forEach((star, index) => {
      star.classList.toggle('hovered', index  {
  stars.forEach((star) => star.classList.remove('hovered'));
});

container.addEventListener('click', (event) => {
  if (event.target.tagName === 'I') {
    const ratingValue = parseInt(event.target.dataset.ratingValue, 10);
    stars.forEach((star, index) => {
      star.classList.toggle('selected', index < ratingValue);
    });

    const ratingChangeEvent = new CustomEvent('rating-change', {
      detail: ratingValue,
    });
    container.dispatchEvent(ratingChangeEvent);
  }
});
  • 부모 컨테이너(container)에 단일 리스너를 추가하여 모든 별의 이벤트를 처리함.
  • 동적으로 추가된 별점도 자동으로 처리 가능.
  • 성능 최적화 측면에서 유리함
profile
측정할 수 없으면 관리할 수 없고, 관리할 수 없으면 개선시킬 수도 없다

0개의 댓글