-
[JS/DOM] 바닐라 자바스크립트로 Tab 탭 구현하기Frontend 2019. 4. 2. 10:04Raw denim you probably haven't heard of them jean shorts Austin. Nesciunt tofu stumptown aliqua, retro synth master cleanse. Mustache cliche tempor, williamsburg carles vegan helvetica. Reprehenderit butcher retro keffiyeh dreamcatcher synth. Cosby sweater eu banh mi, qui irure terry richardson ex squid. Aliquip placeat salvia cillum iphone. Seitan aliquip quis cardigan american apparel, butcher voluptate nisi qui.
오늘은 실무에서 참 많이 쓰는 탭(Tab)을
바닐라 자바스크립트만 사용해서 구현해보려고 한다.
먼저 HTML 구조는 다음과 같다.
<HTML>
<div class="tab_basic"> <div class="tab_list_wrap"> <div class="tab_list tab_active" data-tabnum="0"> <a href="#">1번 탭</a> </div> <div class="tab_list" data-tabnum="1"> <a href="#">2번 탭</a> </div> <div class="tab_list" data-tabnum="2"> <a href="#">3번 탭</a> </div> </div> <div class="tab_container"> <div class="tab_content"> Raw denim you probably haven't heard of them jean shorts Austin. Nesciunt tofu stumptown aliqua, retro synth master cleanse. Mustache cliche tempor, williamsburg carles vegan helvetica. Reprehenderit butcher retro keffiyeh dreamcatcher synth. Cosby sweater eu banh mi, qui irure terry richardson ex squid. Aliquip placeat salvia cillum iphone. Seitan aliquip quis cardigan american apparel, butcher voluptate nisi qui. </div> <div class="tab_content"> Food truck fixie locavore, accusamus mcsweeney's marfa nulla single-origin coffee squid. Exercitation +1 labore velit, blog sartorial PBR leggings next level wes anderson artisan four loko farm-to-table craft beer twee. Qui photo booth letterpress, commodo enim craft beer mlkshk aliquip jean shorts ullamco ad vinyl cillum PBR. </div> <div class="tab_content"> Homo nostrud organic, assumenda labore aesthetic magna delectus mollit. Keytar helvetica VHS salvia yr, vero magna velit sapiente labore stumptown. Vegan fanny pack odio cillum wes anderson 8-bit, sustainable jean shorts beard ut DIY ethical culpa terry richardson biodiesel. Art party scenester stumptown, tumblr butcher vero sint qui sapiente accusamus tattooed echo park. </div> </div> </div>
<CSS>
.tab_basic { width: 80%; margin: auto; } .tab_list_wrap { font-size: 0; height: 35px; } .tab_list { display: inline-block; width: 33.3334%; height: 100%; font-size: 15px; line-height: 30px; text-align: center; border: 1px solid #eee; border-right: 0; box-sizing: border-box; } .tab_list:last-child { border-right: 1px solid #eee; } .tab_list.tab_active { background: #eee; } .tab_list a { display: block; width: 100%; height: 100%; text-decoration: none; color: #222; } .tab_content { display: none; width: 100%; min-height: 100px; padding: 20px; background: #eee; box-sizing: border-box; } .tab_content:first-child { display: block; }
.tab_active라는 클래스로 ACTIVE 상태인 탭의 배경색깔을 회색으로 바꿔줄 생각이다.
일단 .tab_list > a 태그를 클릭했을 때 이벤트를 걸어주려고 한다.
var tabList = document.querySelectorAll('.tab_list_wrap .tab_list') Array.prototype.forEach.call(tabList, function(list) { list.children[0].addEventListener('click', function(e) { e.preventDefault() }) })
이렇게 구현할 수 있는데 먼저 Array.prototype.forEach.call()이 뭔지 알아야한다.
탭 3개를 클릭했을 때 이벤트를 걸어야하니까 일단
tabList라는 변수에 document.querySelectorAll('.tab_list_wrap .tab_list')를 할당했다.
그러면 .tab_list라는 클래스를 가진 모든 dom을 유사배열로 가져오게 된다.
내가 테스트해본 결과 이 유사배열을 for문으로 돌려서 이벤트를 걸면 이벤트가 잘 동작한다.
그러나 이건 진짜 배열이 아니고 유사배열이라서 forEach()같은 함수들을 사용할 수 없다.
(근데 또 크롬에서는 된다. 그치만 우린 익스플로러나 다른 브라우저도 맞춰주어야하니까..)
그 때 사용하는 것이 call이나 apply이다.
사용법은 다음과 같다.
var domArray = document.querySelectorAll('.class_name') // apply Array.prototype.forEach.apply(domArray, [function(elem) { console.log(elem) }]) // call Array.prototype.forEach.call(domArray, function(elem) { console.log(elem) })
나는 이 둘 중에서 더 간단해보이는 call을 사용했다.
call을 이용해서 .tab_list를 list라는 이름으로 받아왔고
그 list의 children인 a태그에 클릭이벤트를 주었는데
여기서 중요한건 꼭 preventDefault()를 걸어줘야한다는거다.
왜냐면 a태그는 기본적으로 페이지 이동이라는 기능이 있는데,
우리는 탭 구현에 a태그를 사용할거니까 페이지가 이동되는걸 막아주어야 한다.
그 때 사용하는 것이 preventDefault()이다.
하여튼 a태그를 클릭할 때 클릭된 .tab_list의 data-num이라는 속성값을 가져와 tabNum이라는 변수에 담는다.
그리고 3개의 .content 태그 중에서 tabNum과 동일한 인덱스 번호를 가지는 태그를 display: block으로 바꿔주고
나머지 .content는 모두 display: none으로 바꿔준다.
var tabList = document.querySelectorAll('.tab_list_wrap .tab_list') Array.prototype.forEach.call(tabList, function(list) { list.children[0].addEventListener('click', function(e) { e.preventDefault() var tabContent = document.querySelectorAll('.tab_container .tab_content') var tabNum = this.parentElement.getAttribute('data-tabnum') Array.prototype.forEach.call(tabContent, function(cont, i) { cont.style.display = 'none' }) tabContent[tabNum].style.display = 'block' }) })
이제 마지막으로 해야할 것은 클릭된 .tab_list에 .tab_active라는 클래스를 추가해주는 것이다.
자바스크립트로 클래스를 제어하는 방법은 여러가지가 있는데,
그 중에서 제이쿼리랑 제일 비슷하고 쉽게 느껴졌던 방법은 아래와 같다.
Dom.classList.remove('class_name') // $(dom).removeClass('class_name') Dom.classList.add('class_name') // // $(dom).addClass('class_name') Dom.classList.contains('class_name') // $(dom).hasClass('class_name')
근데 classList는 IE9이하 버전에서는 작동하지 않는다. 하.. 익스..
그래서 classList대신 className을 이용하기로 했다.
var tabList = document.querySelectorAll('.tab_list_wrap .tab_list') Array.prototype.forEach.call(tabList, function(list) { list.children[0].addEventListener('click', function(e) { e.preventDefault() var tabContent = document.querySelectorAll('.tab_container .tab_content') var tabNum = this.parentElement.getAttribute('data-tabnum') Array.prototype.forEach.call(tabContent, function(cont, i) { cont.style.display = 'none' tabList[i].className = 'tab_list' }) tabContent[tabNum].style.display = 'block' if(list.className.indexOf('tab_active') == -1) { list.className = 'tab_list tab_active' } }) })
모든 .tab_list의 클래스는 tab_list 하나로 해주고
내가 클릭한 .tab_list에만 tab_list tab_active 두개의 클래스를 넣어주면 된다.
끝!
- 아래 탭으로 테스트 가능합니다. -
Raw denim you probably haven't heard of them jean shorts Austin. Nesciunt tofu stumptown aliqua, retro synth master cleanse. Mustache cliche tempor, williamsburg carles vegan helvetica. Reprehenderit butcher retro keffiyeh dreamcatcher synth. Cosby sweater eu banh mi, qui irure terry richardson ex squid. Aliquip placeat salvia cillum iphone. Seitan aliquip quis cardigan american apparel, butcher voluptate nisi qui.See the Pen Tab by juyeonH (@JY712) on CodePen.
반응형'Frontend' 카테고리의 다른 글
[JS/DOM] 바닐라 자바스크립트로 스톱워치(STOP WATCH)구현하기 (10) 2019.04.04 [JS/DOM] 바닐라 자바스크립트로 전자시계 구현하기 (날짜/시간 출력) (5) 2019.04.02 [CSS] :before, :after에 counter()를 사용하여 숫자 리스트 표현하기 (0) 2019.03.24 [JS/DOM] 바닐라 자바스크립트로 select태그 option 동적으로 생성, 삭제하기 / 특정 옵션 선택하기 (2) 2019.03.24 [JS/DOM] 바닐라 자바스크립트로 테이블 행 삭제 버튼 구현하기 (2) 2019.03.24 COMMENT