본문 바로가기

Javascript/활용팁&실전예제

이벤트 위임으로 메뉴 선택 구현하기

반응형

이벤트 델리게이션을 사용해 관리하기 편한 메뉴 구조를 만들 수 있습니다.

이벤트 델리게이션을 사용하면, 메뉴 추가나 변경에 따르는 이벤트 처리 작업을 최소화 할 수 있고, HTML/CSS 와 자바스크립트가 깨끗하게 분리되기 때문에 유지보수 및 협업에서도 유리합니다.


아래와 같은 구조를 가지는 가로 메뉴를 이벤트 델리게이션으로 메뉴 클릭 이벤트 처리를 해보겠습니다.

메뉴 항목 클릭시 AJAX로 페이지 내용을 가져와 페이지 갱신 없이 메뉴를 이동하는 웹사이트 제작에 사용할 수 있습니다.


예제의 CSS는 기본 레이아웃만 적용되어있습니다.

각 메뉴 항목은 이벤트 버블링을 이용한 이벤트 델리게이션 사용 예를 보기 위해 여러겹의 태그로 감싼 것입니다.


<style>
    .menuwrap{
        width100%;
        text-aligncenter;
    }      
    .menu{
      positionrelative;
      margin0 auto;
      list-stylenone;
    }
    .menu li{
      font-size0.9375em;
      padding5px 15px;
      text-aligncenter;
      displayinline-block;
      cursorpointer;
      padding10px;
    }
    .menu li a{
        padding10px;
    }
    .menu li a span{
        padding10px;
    }
    .active{
        font-weightbold;
        border-bottom2px solid #a00;
        color#a00;
    }
  </style>

<div class="menuwrap">
    <ul class="menu">
        <li class="item" data-menuid="0"><a class="active"><span>메인</span></a></li>
        <li class="item" data-menuid="1"><a><span>소개</span></a></li>
        <li class="item" data-menuid="2"><a><span>상품</span></a></li>
        <li class="item" data-menuid="3"><a><span>고객지원</span></a></li>
        <li class="item" data-menuid="4"><a><span>오시는길</span></a></li>
    </ul>
</div>



이벤트 위임(Deligation)으로 메뉴 항목 클릭에 반응하기 위해서는 중첩된 요소들 중에 어떤 것이 클릭한 건지 알아야 합니다.

개별 메뉴 항목 안에 중첩된 내부 요소에 패딩이 있으면 겹치지 않는 영역이 생기면서 <li>, <a>, <span> 중 어느 한 태그 영역을 클릭하게 됩니다.


실제로는 AJAX로 페이지 정보를 가져오기 위해 필요한 정보로 "menuid" 값이 필요하고, <li> 태그의 "menuid" 속성값을 알아야 합니다.

따라서, 중첩된 내부 요소를 클릭한 경우 상위의 <li> 요소 엘리먼트 노드를 알아내야 합니다.


콜백 함수의 이벤트 파라메터 객체에서 클릭한 타겟 요소를 얻은 후 태그 이름에 따라 부모 요소로 올라가 <li> 태그 요소를 얻습니다.


let clickli = event.target.tagName == 'A' ? event.target.parentNode: (event.target.tagName == 'SPAN' ? event.target.parentNode.parentNode : event.target);


<ll> 요소를 얻었으므로 기존 선택 메뉴의 "active" 클래스를 지우고 클릭한 새 메뉴 항목에 "active" 클래스를 추가해 활성화합니다.


마지막으로 새로 선택한 메뉴의 페이지를 가져오기 위한 "menuid" 값을 알아야 합니다.


"clickli.getAttribute('data-menuid')", 또는 "clickli.dataset.menuid" 로 "menuid" 값을 얻습니다.


이벤트 위임을 이용하면 각 메뉴 항목마다 이벤트를 등록할 필요가 없어집니다.없이, 

전체 메뉴 항목 영역에 이벤트 리스너를 등록함으로써 이벤트 버블링(Event Bubbling)으로 올라오는 이벤트를 캡쳐해 선택한 메뉴에 대한 정보를 얻을 수 있습니다.


document.addEventListener('DOMContentLoaded'function(){ // DOM 로딩 후 이벤트 리스너 등록
    document.querySelector('.menu').addEventListener('click'function(e){ // 전체 메뉴영역을 클릭하는 이벤트 리스너 등록
        //클릭 메뉴 항목 찾기
        let target = e.target// 클릭한 엘리먼트 
        //UL 리스트 아이템인 <li> 엘리먼트를 얻기 위해 <li> 하위에서 클릭한 태그에 따라 상위 부모를 찾는 방법을 다르게함.
        let clickli = target.tagName == 'A' ? target.parentNode: (target.tagName == 'SPAN' ?
            target.parentNode.parentNode : target);
        
        if(clickli){
            //현재 활성 메뉴 초기화
            let currentCategory = document.querySelector('.menu a.active');
            if(currentCategory){
                currentCategory.classList.remove('active');
            }
            
            //새 선택 메뉴 활성화
            clickli.querySelector('a').classList.add('active');

            let pageURL = "/api/page?menuid="+clickli.getAttribute('data-menuid');
            
//AJAX로 새로 로딩할 새 페이지 내용을 가져옴.
        }
    });
});




반응형

닫기