오늘은 vue에서 아코디언 메뉴 만드는 방법을 포스팅해보도록 하겠습니다.
개요
- 반복문을 사용해 생성한 각 아코디언 탭 컨텐츠는 개별적으로 열고 닫을 수 있다. (하나의 탭을 open했을 때 나머지 탭이 닫히면 안됨)
우리가 이전에 jQuery 또는 Es6 자바스크립트로 아코디언 메뉴를 만들 때에는 for문 등의 반복문을 사용하더라도 간단하게 toggle이라는 함수를 사용해서 아코디언 기능을 만들 수 있었는데요 vue나 react에서는 약간의 차이가 있습니다.
예를 들어 Es6에서 아코디언 아이템들이 여러개 있다고 하더라도 별도의 준비 없이 클릭하는 아이템에 해당하는 인덱스를 활용하여 아래와 같이 토글 함수를 이용해 간단히 클릭하는 item의 index를 열고 닫고를 처리할 수 있었습니다.
item.classList.toggle('active');
마찬가지로 jquery 에서도 .slideToggle() 함수를 사용해 매우 간단하게 구현이 가능했습니다.
$('.items').toggleClass('active')
$('.items').slideToggle()
Vue, React에서는 상태를 따로 관리해야 구현 가능
- 각각 독립적으로 관리할 수 있는 상태값을 먼저 셋팅해주어야 한다.
Vue나 React와 같은 SPA언어에서는 열고 닫히는 상태값을 아이템 각각이 가지고 있어야 개별적으로 열고 닫을 수 있는 기능(아코디언)을 구현할 수 있습니다.
예를 들어 아래와 같이 isOpen이라는 key값으로 오픈 상태를 관리하는 것입니다.
const items = ref([
{
title:'아코디언',
content:'컨텐츠츠컨텐컨텐츠츠',
isOpen:false
},
{
title:'아코디언',
content:'컨텐츠츠텐츠츠컨텐츠츠컨텐츠츠컨텐츠츠',
isOpen:false
},
{
title:'아코디언',
content:'컨텐츠츠컨텐츠츠컨텐츠츠컨텐츠츠',
isOpen:false
},
{
title:'아코디언',
content:'컨텐츠츠',
isOpen:false
},
{
title:'아코디언',
content:'컨텐츠츠컨츠컨텐츠츠',
isOpen:false
},
])
위 코드를 보면 각 아이템들이 isOpen이라는 상태값을 독립적으로 가지고 있습니다.
이런 방법식은 이전 jQuery 나 Es6 생각한다면 조금 귀찮게 느껴지는 부분인데요 이렇게 오픈 상태를 관리할 수 있는 값만 셋팅해둔다면 이후 코딩은 이전 jQuery 나 Es6와 마찬가지로 심플합니다.
vue3로 구현된 코드를 보겠습니다.
@click="item.isOpen = !item.isOpen" // item.isOpen 상태를 !item.isOpen로 할당한다
위 코드를 간단히 설명하자면
- !item.isOpen은 item.isOpen이 true 이면 false로 할당하고 false면 true로 할당하는 방식
- !를 사용해서 현재의 반대 상태로 할당시켜주는 의미
아래 완성된 코드를 보겠습니다.
<template>
<section>
<div class="accordion-wrap">
<div
class="accordion-item"
v-for="(item, index) in items" :key="index"
>
<button @click="item.isOpen = !item.isOpen">
{{item.title}}
</button>
<div class="cont"
v-if="item.isOpen"
v-html="item.content"
>
</div>
</div>
</div>
</section>
</template>
위는 accordion-item 을 items라는 배열만큼 반복문을 돌려서 출력하는 코드입니다.
<button> 요소에 클릭 이벤트를 걸어주어 item.isOpen = !item.isOpen 상태값을 계속해서 바꿔줌으로 open/close 동작을 하게 합니다.
버튼 영역에 {{item.title}} 는 속성값을 출력해주는 문법입니다.
<div class="cont"> 영역에서는 v-html 을 사용했는데 속성값에 "<br>컨텐츠츠<br>컨텐츠" html 태그가 있을 경우에는 {{item.content}} 대신 v-html="item.content" 사용해주어야 하는 부분도 알아두시면 좋습니다.
완성 코드
<template>
<section>
<div class="accordion-wrap">
<div
class="accordion-item"
v-for="(item, index) in items" :key="index"
>
<button @click="item.isOpen = !item.isOpen">
{{ index+1 }}번 {{item.title}}
</button>
<div class="cont"
v-if="item.isOpen"
v-html="item.content"
>
</div>
</div>
</div>
</section>
</template>
<script setup>
import { ref } from 'vue'
const items = ref([
{
title:'아코디언',
content:'컨텐츠츠<br>컨텐츠츠컨텐츠<br>츠컨텐츠츠컨<br>텐츠츠컨텐츠츠<br>컨텐츠츠컨텐츠츠',
isOpen:false
},
{
title:'아코디언',
content:'컨텐츠츠<br>컨텐츠츠컨텐츠<br>츠컨텐츠츠컨<br>텐츠츠컨텐츠츠<br>컨텐츠츠컨텐츠츠',
isOpen:false
},
{
title:'아코디언',
content:'컨텐츠츠<br>컨텐츠츠컨텐츠<br>츠컨텐츠츠컨<br>텐츠츠컨텐츠츠<br>컨텐츠츠컨텐츠츠',
isOpen:false
},
{
title:'아코디언',
content:'컨텐츠츠<br>컨텐츠츠컨텐츠<br>츠컨텐츠츠컨<br>텐츠츠컨텐츠츠<br>컨텐츠츠컨텐츠츠',
isOpen:false
},
{
title:'아코디언',
content:'컨텐츠츠<br>컨텐츠츠컨텐츠<br>츠컨텐츠츠컨<br>텐츠츠컨텐츠츠<br>컨텐츠츠컨텐츠츠',
isOpen:false
},
])
</script>
최종 결과 화면
다음 포스팅에서는 열고 닫히는 액션에 부드러운 효과를 추가해보도록 하겠습니다.
그럼 이만🤚
'프로그래밍 > vue.js' 카테고리의 다른 글
vue3 Transition 을 이용한 아코디언 기능(부드럽게 열고 닫기) (0) | 2025.05.19 |
---|---|
vue3 아코디언 메뉴 부드럽게 열고 닫기 event.target (0) | 2025.05.10 |
vue3 아코디언 메뉴 부드럽게 열고 닫히게 (0) | 2025.05.06 |
vue.js SPA(싱글 페이지 어플리케이션) 이란? (2) | 2025.04.12 |