본문 바로가기

Language & Framework/JavaScript

바닐라 자바스크립트로 data 속성 사용하여 탭(Tab) 기능 만들기.

이 방법을 사용하여 탭 기능을 만들기 위해서는 JavaScript의 forEach와 HTML의 데이터 속성에 대한 사전 지식이 필요하다.

(대충만 알면 만들 수 있음)

 

일단 데이터 속성에 관한 자세한 설명이 궁금하다면 여기를 참고할 것.

 

간단하게 설명하자면 사용자 인터페이스에는 노출되지 않는 추가적인 정보를 HTML에 저장하여 JavaScript로 불러올 수 있도록 하는 것이다. 참고로 이 데이터 속성은 사용자 인터페이스에 노출되지 않는다는 것이지 개발자 툴에서 모두 확인 가능하므로 중요한 정보를 이 안에 담아서는 안 된다.

html에 data 속성을 담을 때는 data-원하는이름 = "문자열", JavaScript에서 이 속성을 불러올 때는 Element.dataset.원하는이름으로 불러오면 된다.

 

두 번째로 ForEach는 어떤 배열이 있을 때 그 배열의 요소를 각각 실행하는 역할을 한다. 역시나 자세한 건 여기로 가서 정확한 지식을 배우길 바랍니다.

제이쿼리(Jquery)를 사용하면 복수의 요소를 별다른 문법을 사용하지 않고도 호출할 수 있지만 바닐라 자바스크립트에서는 ForEach(혹은 Map) API를 사용하지 않으면 배열의 요소를 한 개씩 일일히 따로 호출해줘야 한다.

 

 

 

HTML

    <div class="tab">
        <ul class="tab__list">
            <li class="tab__list__item" data-list="1">
                웅이의 유년시절
            </li>
            <li class="tab__list__item active" data-list="2">
                웅이의 매력포인트
            </li>
            <li class="tab__list__item" data-list="3">
                웅이의 미래
            </li>
        </ul>
        <div class="tab__contents" data-order="1">
            웅이는 행복하게 자랐습니다
        </div>
        <div class="tab__contents show" data-order="2">
            웅이는 바보 같아서 귀엽습니다
        </div>
        <div class="tab__contents" data-order="3">
            웅이는 남은 여생을 행복하게 지낼 예정입니다
        </div>
    </div>

" 내가 이 탭을 눌렀을 때 이 메뉴를 보여주십시오. " 를 data 속성을 이용하여 컴퓨터한테 시키려면 어떻게 해야할까?

" 내가 1이라는 값을 가진 data를 가진 요소를 눌렀을 때 1이라는 값을 가진 data를 가진 같은 요소를 보여주세요 "라고 해야 한다.

data 뒤의 이름은 중요하지 않지만 탭 항목의 값과 탭을 누르면 보여줄 컨텐츠의 값이 같아야 한다는 말이다.

 

 

 

CSS

    <div class="tab">
        <ul class="tab__list">
            <li class="tab__list__item" data-list="1">
                웅이의 유년시절
            </li>
            <li class="tab__list__item active" data-list="2">
                웅이의 매력포인트
            </li>
            <li class="tab__list__item" data-list="3">
                웅이의 미래
            </li>
        </ul>
        <div class="tab__contents" data-order="1">
            웅이는 행복하게 자랐습니다
        </div>
        <div class="tab__contents show" data-order="2">
            웅이는 바보 같아서 귀엽습니다
        </div>
        <div class="tab__contents" data-order="3">
            웅이는 남은 여생을 행복하게 지낼 예정입니다
        </div>
    </div>

 

오직 기능 구현만을 위해 대충 만든 CSS이기 때문에 다른 걸 원하면 직접 꾸미면 된다.

나는 평상시에는 display : none, 특정 클래스가 붙으면 display : block이 되도록 만들었다.

 

 

 

Java Script


const tab = document.querySelector(".tab");
const tabListItem = document.querySelectorAll(".tab__list__item");
const tabContent = document.querySelectorAll(".tab__contents");
const active = document.querySelector(".active");
const showing = document.querySelector("show");

tab.addEventListener("click", (e) => {
  const ListOrder = e.target.dataset.list;
  tabListItem.forEach(function (e) {
    e.classList.remove("active");
  });
  e.target.classList.add("active");
  tabContent.forEach(function (event) {
    if (event.dataset.order == ListOrder) {
      event.classList.add("show");
    } else event.classList.remove("show");
  });
});

 

컨테이너 역할을 하고 있는 박스와 항목, 컨텐츠, 그리고 클릭시 active 효과를 줄 클래스를 모두 호출한다.

 

각 카테고리에 이벤트 리스너를 만들어주는 것이 아니라 부모한테 이벤트 리스너를 만들어주는 것이다.

이게 가능한 이유는 e.target을 이용하면 이벤트 리스너가 알아서 " 아~ 이 카테고리를 누르라는 거구나~"하고 알아서 실제 클릭하고 있는 요소한테 이벤트를 실행해주기 때문이다.

이게 불가능했다면 모든 항목에게 따로따로 이벤트 리스너를 만들어줬어야 한다. 으.

 

먼저 tabListItem의 배열을 빙글빙글 돌며 모든 항목의 active를 제거하고 내가 실제로 클릭한 항목에만 active 클래스를 부여한다.

 

그리고 tabContent의 배열을 빙글빙글 돌며 해당 요소가 ListOrder( 위에서 클릭한 요소의 데이터 값 )과 동일한 데이터 값을 가지고 있다면 show 클래스를 부여하고, 그게 아닐 경우 show 클래스를 제거한다.

중요한 건 forEach문에서는 target이 아니라 그냥 event.dataset이다.

 

이렇게하면 탭 만들기 끝. 간단하다.