인프런 커뮤니티 질문&답변

LEETY님의 프로필 이미지
LEETY

작성한 질문수

인터랙티브 웹 개발 제대로 시작하기

3개의 문에서 질문드려요

작성

·

241

0

3개의 문 현재의 순서값에 클래스가 붙는걸 활용해서

텝 메뉴를 만들고자 합니다.

순서값을 .box에 어떻게 전달해야 할까요? 

jquery에서는 간단히 this.index()로 알아냈는데 javascript로는 어렵네요.  팁을 알려주시면 감사하겠습니다.   

 <div id="wrap">

        <div class="content">

            <ul class="menu">

                <li ><a href="#" class="btn"> 0menu</a></li>

                <li><a href="#" class="btn"> 1menu</a></li>

                <li><a href="#" class="btn"> 2menu</a></li>

                <li><a href="#" class="btn"> 3menu</a></li>

            </ul>

            <ul class="box">

                <li class="inner b01 Active">content01</li>

                <li class="inner b02">content02</li>

                <li class="inner b03">content03</li>

                <li class="inner b04">content04</li>

            </ul>

        </div>

    </div>

    <script>

        (function(){

            const menuList = document.querySelector('.menu');

            let currentItem;

            const content=document.querySelector('.box');

            function handler(e){

                const targetElem = e.target;

                // console.log(targetElem);

                if(currentItem){

                    currentItem.classList.remove('On');

                }

                if(targetElem.classList.contains('btn')){

                    targetElem.parentNode.classList.add('On');

                    currentItem= targetElem.parentNode;

                }

              

            }

            menuList.addEventListener('click',handler);

        })()

    </script>

답변 5

1

LEETY님의 프로필 이미지
LEETY
질문자

감사합니다:) 또 배우고 가네요~ 추석 잘 보내세요!

1

1분코딩님의 프로필 이미지
1분코딩
지식공유자

childNodes는 텍스트노드들까지 모두 포함하고 있어서 컨트롤하기가 번거롭기때문에, 관리할 객체들을 따로 querySelectorAll로 선택해두고 사용하시는게 좋습니다. (에러는 텍스트노드의 경우는 classList 속성을 갖고있지 않기 때문에 발생한 것이고요)

작성하신 코드를 최대한 살려서 동작하도록 바꿔봤습니다~

<!DOCTYPE html>

<html lang="en">
  <head>
    <meta charset="UTF-8" />

    <meta name="viewport" content="width=!, initial-scale=1.0" />

    <title>Document</title>

    <style>
      * {
        margin: 0;
        padding: 0;
        box-sizing: border-box;
      }

      ul {
        list-style-type: none;
      }

      #wrap {
        width: 100vw;

        height: 100vh;

        background-color: #eee;

        display: flex;

        align-items: center;

        justify-content: center;
      }

      .content {
        width: 30vw;

        height: 30vw;

        border: 1px solid #000;
      }

      .menu {
        display: flex;
      }

      .menu li {
        width: 25%;

        text-align: center;

        border-right: 1px solid #fff;

        height: 25px;
      }

      .menu li a {
        display: block;

        color: #fff;

        background-color: rgb(109, 198, 240);

        height: 25px;

        text-decoration: none;
      }

      .menu li.On a {
        background-color: #000;
      }

      .menu li:last-child {
        border-right: none;
      }

      .box {
        width: 100%;

        height: calc(100% - 25px);

        position: relative;
      }

      .box .inner {
        position: absolute;

        width: 100%;

        height: 100%;

        font-size: 5vw;

        justify-content: center;

        display: flex;

        align-items: center;

        opacity: 0;
      }

      .box .inner.Active {
        opacity: 1;
      }

      .box .inner.b01 {
        background-color: rgb(113, 156, 236);
      }

      .box .inner.b02 {
        background-color: rgb(236, 113, 195);
      }

      .box .inner.b03 {
        background-color: rgb(236, 199, 113);
      }

      .box .inner.b04 {
        background-color: rgb(236, 172, 113);
      }
    </style>
  </head>

  <body>
    <div id="wrap">
      <div class="content">
        <ul class="menu">
          <li class="On"><a href="#" class="btn"> 0menu</a></li>

          <li><a href="#" class="btn"> 1menu</a></li>

          <li><a href="#" class="btn"> 2menu</a></li>

          <li><a href="#" class="btn"> 3menu</a></li>
        </ul>

        <ul class="box">
          <li class="inner b01 Active" data-index="0">content01</li>

          <li class="inner b02" data-index="1">content02</li>

          <li class="inner b03" data-index="2">content03</li>

          <li class="inner b04" data-index="3">content04</li>
        </ul>
      </div>
    </div>

    <script>
      (function () {
        const menuList = document.querySelector(".menu");
        const content = document.querySelector(".box");
		const inner = content.querySelectorAll('.inner');
		
		let currentItem = menuList.querySelector('.On');
        let currentContent = content.querySelector('.Active');

        function handler(e) {
          const targetElem = e.target;

          // console.log(targetElem);

          if (currentItem) {
            currentItem.classList.remove("On");
            currentContent.classList.remove("Active");
          }

          if (targetElem.classList.contains("btn")) {
            targetElem.parentNode.classList.add("On");
            inner[targetElem.dataset.index].classList.add("Active");

            currentItem = targetElem.parentNode;
			currentContent = inner[targetElem.dataset.index];
			console.log(currentContent);
          }
        }

        menuList.addEventListener("click", handler);

        // data-index 추가

        menuList.querySelectorAll(".btn").forEach(function (item, i) {
          item.dataset.index = i;

          console.log(i);

          // if (content.childNodes.classList.contains("inner")) {
          //   content.childNodes.dataset.index[i].classList.add("Active");
          // }
        });
      })();
    </script>
  </body>
</html>

0

1분코딩님의 프로필 이미지
1분코딩
지식공유자

네 JOON님도 추석 잘 보내세요^^

0

LEETY님의 프로필 이미지
LEETY
질문자

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=!, initial-scale=1.0">
    <title>Document</title>
    <style>
        *{margin:0;padding:0;box-sizing: border-box;}
        ul{list-style-type:none;}
        #wrap {
            width:100vw;
            height:100vh;
            background-color:#eee;
            display:flex;
            align-items:center;
            justify-content:center;
        }
        .content{
            width:30vw;
            height:30vw;
            border:1px solid #000;
        }
        .menu {
            display:flex;
           
        }
        .menu li{
            width:25%;
            text-align:center;
            border-right:1px solid #fff;
            height:25px;
        }
        .menu li a{
            display:block;
            color:#fff;
            background-color:rgb(109198240);
            height:25px;
            text-decoration:none;
        }
        .menu li.On a{
            background-color:#000;

        }
        .menu li:last-child{
            border-right:none;
        }
        .box {
            width:100%;
            height:calc(100% - 25px);
            position:relative;

        }
        .box .inner{
            position:absolute;
            width:100%;
            height:100%;
            font-size:5vw;
            justify-content:center;
            display:flex;
            align-items:center;
            opacity:0;
        }
        .box .inner.Active{
            opacity:1
        }
        .box .inner.b01{
            background-color:rgb(113156236);
        }
        .box .inner.b02{
            background-color:rgb(236113195);
        }
        .box .inner.b03{
            background-color:rgb(236199113);
        }
        .box .inner.b04{
            background-color:rgb(236172113);
        }
    </style>
</head>
<body>
    <div id="wrap">
        <div class="content">
            <ul class="menu">
                <li ><a href="#" class="btn"> 0menu</a></li>
                <li><a href="#" class="btn"> 1menu</a></li>
                <li><a href="#" class="btn"> 2menu</a></li>
                <li><a href="#" class="btn"> 3menu</a></li>
            </ul>
            <ul class="box">
                <li class="inner b01 Active" data-index="0">content01</li>
                <li class="inner b02" data-index="1">content02</li>
                <li class="inner b03" data-index="2">content03</li>
                <li class="inner b04" data-index="3">content04</li>
            </ul>
        </div>
    </div>
    <script>
        (function(){
            const menuList = document.querySelector('.menu');

            let currentItem;
            const content=document.querySelector('.box');
            const inner = content.childNodes;
            console.log(inner);

            function handler(e){
                const targetElem = e.target;
                // console.log(targetElem);

                if(currentItem){
                    currentItem.classList.remove('On');
                }
                if(targetElem.classList.contains('btn')){
                    targetElem.parentNode.classList.add('On');

                    currentItem= targetElem.parentNode;

                }

              
            }

            menuList.addEventListener('click',handler);

            // data-index 추가
        menuList.querySelectorAll(".btn").forEach(function (item, i) {
          item.dataset.index = i;
          console.log(i)

            if(content.childNodes.classList.contains('inner')){

                content.childNodes.dataset.index[i].classList.add('Active')
            }

 

        });
        })()
    </script>
</body>
</html>
이렇게 쓰니 에러가 뜨네요~ ㅜㅜ 자식요소의 dataset중 index가 i 인 아이한테 클래스 붙여라라고 생각한건데 잘못된 점이 무었일까요

0

1분코딩님의 프로필 이미지
1분코딩
지식공유자

dataset 객체(data- 속성)을 이용하시면 쉽습니다.
아래와 같은 형태로 쓸 수 있는 표준 사용자정의 속성이라고 생각하시면 됩니다~
여기서 myname 부분은 직접 이름을 지으시면 됩니다.
<span data-myname="100"></span>
이렇게 하면 해당 span 객체에는
span객체.dataset { myname: 100 }
이런 속성이 자동으로 추가됩니다.

작성하신 코드에 data-index를 0부터 차례로 넣어주고, 클릭했을 때 콘솔 로그에 출력해보는 코드를 추가해 봤습니다.
html에 직접 넣으셔도 되고, 아래처럼 스크립트로(forEach) 넣어주셔도 되고요.
span객체.getAttribute("data-index")으로 이용하셔도 되고,
span객체.dataset.index로 접근하셔도 됩니다.

(function () {
        const menuList = document.querySelector(".menu");

        let currentItem;

        const content = document.querySelector(".box");

        function handler(e) {
          const targetElem = e.target;

          // console.log(targetElem);

          if (currentItem) {
            currentItem.classList.remove("On");
          }

          if (targetElem.classList.contains("btn")) {
            targetElem.parentNode.classList.add("On");

            currentItem = targetElem.parentNode;

            // data-index 출력
            console.log(targetElem.dataset.index);
          }
        }

        menuList.addEventListener("click", handler);

        // data-index 추가
        menuList.querySelectorAll(".btn").forEach(function (item, i) {
          item.dataset.index = i;
        });
      })();

LEETY님의 프로필 이미지
LEETY

작성한 질문수

질문하기