くるみ
- Vue.jsで開閉するメニューを作りたい
- 初心者でも簡単にコーディオンメニューを作る方法を探している
ということで今回はVue.jsで開閉するアコーディオンメニューを爆速で作っていこうと思います。
ブログ主の備忘録代わりでもありますが参考になれば幸いです⸝⸝- ̫ -⸝⸝
お品書き
アコーディオンメニューの完成イメージ
この「ぽてちる」というサイトではWordPressのカスタマイズ情報や日々のプログラミングの勉強について発信しています。
サイトの居心地の良さと、記事の読みやすさ・分かりやすさにはかなり力を入れています。
よく出てくる茶髪で頭にリボンを付けた女の子は「くるみ」という名前の女の子です。ブログ主が一から作りました。可愛いでしょ。
今回はこのようなアコーディオンメニューをVueを使って作ります。よく見る定番のやつですね。
くるみ
Vueでアコーディオンメニューを作る方法
コンポーネントを作る
Vue.component("accordion", {
template: `
<div class="accordion">
<div class="title" @click="open()">
<slot name="title"></slot>
<transition name="rotate" mode="out-in">
<i class="fas fa-chevron-up" v-if="isOpen" key="rotate1"></i>
<i class="fas fa-chevron-down" v-else key="rotate2"></i>
</transition>
</div>
<transition name="open">
<div class="accordion-content" v-if="isOpen">
<slot name="content"></slot>
</div>
</transition>
</div>`,
data: function () {
return {
isOpen: false
}
},
methods: {
open: function () {
this.isOpen = !this.isOpen;
}
}
});
new Vue({
el: "#app"
});
まずaccordionというコンポーネントを作ります。
そしてisOpenというメニューの開閉状態を保存する変数を用意し、それを変える関数openも定義しておきます。
くるみ
テンプレートの内容
<div class="accordion">
<div class="title" @click="open()">
<slot name="title"></slot>
<transition name="rotate" mode="out-in">
<i class="fas fa-chevron-up" v-if="isOpen" key="rotate1"></i>
<i class="fas fa-chevron-down" v-else key="rotate2"></i>
</transition>
</div>
<transition name="open">
<div class="accordion-content" v-if="isOpen">
<slot name="content"></slot>
</div>
</transition>
</div>
まずタイトルと内容を表示するスロットを用意します。
そしてタイトルの矢印アイコンと、内容に関しては関数openで表示・非表示を切り替えます。
あとはisOpenの変化に合わせて矢印のアイコンを上下逆にするために、以下を行います。
- transitionタグにおいて「mode=”out-in”」を指定して、前の矢印が消えてから次の矢印を表示するようにする
- transitionタグの直下なので排他的に表示させるべく、矢印アイコンそれぞれにkey属性も記述する
次はこのコンポーネントを呼び出していきます。
コンポーネントを呼び出す
<div id="app">
<accordion>
<div slot="title">タイトル</div>
<div class="content" slot="content">
<p>ここに内容</p>
</div>
</accordion>
<accordion>
<div slot="title">タイトル</div>
<div class="content" slot="content">
<p>ここに内容</p>
</div>
</accordion>
<accordion>
<div slot="title">タイトル</div>
<div class="content" slot="content">
<p>ここに内容</p>
</div>
</accordion>
</div>
slot属性を忘れずに。
開閉のアニメーションを加える
@keyframes open {
0% {
opacity: 0;
transform: translateY(-5px);
}
100% {
opacity: 1;
transform: translateY(0px);
}
}
.open-enter-active {
animation: open .2s;
}
.open-leave-active {
animation: open .2s linear reverse;
}
次に、アコーディオンメニューの開閉の際のアニメーションを設定していきます。
メニューが閉じる際は動きが滑らかな必要は無いので「linear」を指定しておきます。
アイコンのアニメーションを加える
@keyframes rotate {
0% {
transform: rotate(180deg);
}
}
.rotate-enter-active {
animation: rotate .2s linear;
}
次にメニューの開閉に合わせて矢印アイコンをくるくる回していきます。
ここで一つ注意なのが、必要なセレクタは「.rotate-enter-active」だけでありleave時の「.rotate-leave-active」は要らないということです。
というのも「.rotate-leave-active」も設定してしまうと、消える時と追加される時の両方でアニメーションが発生してしまい余分に回転してしまうからです。
そこさえ注意すればOK。
デザインを整える
.accordion {
max-width: 70%;
margin: 10px auto;
}
.title:hover {
opacity: .8;
cursor: pointer;
}
.title {
margin-bottom: 10px;
background-color: #eee;
padding: 15px;
border-radius: 5px;
}
.title>div {
display: inline-block;
font-weight: bold;
}
.title i {
float: right;
line-height: 1.3;
}
.content {
padding: 0 15px;
margin-bottom: 10px;
}
あとはデザインを整えてあげれば…完成です。
くるみ
まとめ

vue初心者です!とても参考になりました。
私の使い方だと、折りたたむ項目が多量にあるので、v-forでタイトルと内容が格納された配列を回してます。(data()の配列が圧迫されてしまいますが…)