今回はアコーディオンメニューを簡単に実装できる方法について解説していきます。
今回は下記の4つを上手く使って完成させて行きます。
各項目がどの役割を果たすのかを簡単に説明すると以下になります。
- v-for
- メニューを繰り返し表示
- v-if(v-showでも代替え可能)
- 表示と非表示の切り替え
- @click (v-on:click)
- メニューが押されたとき
- transition
- 開くとき、閉じるときのアニメーション
早速全体のコードをみていきましょう!
全体のコード
<template lang="pug">
.page-accordion
h1 アコーディオンメニュー
ul
li(v-for="(menu, index) in menus" @click="isOpen(index)")
p {{ menu.title }}
transition(name="fade")
.menu-content(v-if="menu.flag")
p {{ menu.content }}
</template>
<script>
export default {
data() {
return {
menus: [
{
flag: false,
title: 'メニュータイトル',
content: 'メニューコンテンツ',
},
{
flag: false,
title: 'メニュータイトル',
content: 'メニューコンテンツ',
},
{
flag: false,
title: 'メニュータイトル',
content: 'メニューコンテンツ',
},
{
flag: false,
title: 'メニュータイトル',
content: 'メニューコンテンツ',
},
{
flag: false,
title: 'メニュータイトル',
content: 'メニューコンテンツ',
},
],
}
},
methods: {
isOpen(key) {
this.menus[key].flag = !this.menus[key].flag
},
},
}
</script>
<style lang="stylus">
.page-accordion
ul
width 50%
margin 0 auto
li
border 1px solid #eee
box-sizing border-box
padding 10px
cursor pointer
p
font-size rem(20px)
line-height rem(24px)
.menu-content
border-top 1px solid #eee
margin-top 10px
padding 15px
p
font-size rem(16px)
line-height rem(22px)
.fade-enter-active,
.fade-leave-active
transition opacity 1s
.fade-enter,
.fade-leave-to
opacity 0
</style>
思ったよりも長いと思った方、安心してください、細分化するとやっていることはかなり簡単です。
html(pug)の記述のについて
.page-accordion
h1 アコーディオンメニュー
ul
li(v-for="(menu, index) in menus" @click="isOpen(index)")
p {{ menu.title }}
transition(name="fade")
.menu-content(v-if="menu.flag")
p {{ menu.content }}
htmlの記述はこれだけです。
今回は「li」の中身の表示を切り替えてアコーディオンメニューを再現します。
初期表示で隠れている部分は、「.menu-content」の部分です。
「li」がクリックされたときに、v-ifの値がtrueになり表示されるといった流れになります。
transition
transition(name="fade")
.menu-content(v-if="menu.flag")
v-ifの値がfalseの状態だと、要素自体がない状態になっています。
このときに、アニメーションをつけるために、transitionを使います。
使い方についてはドキュメントに書いてあるのでそちらを参考にしてください。
今回のアニメーションも公式のものを参考にしました。
CSS(stylus)
.page-accordion
ul
width 50%
margin 0 auto
li
border 1px solid #eee
box-sizing border-box
padding 10px
cursor pointer
p
font-size rem(20px)
line-height rem(24px)
.menu-content
border-top 1px solid #eee
margin-top 10px
padding 15px
p
font-size rem(16px)
line-height rem(22px)
.fade-enter-active,
.fade-leave-active
transition opacity 1s
.fade-enter,
.fade-leave-to
opacity 0
スタイルについてはお好みのものがあるかと思いますでの説明は割愛しtransitionのアニメーションの説明だけします。
.fade-enter-active,
.fade-leave-active
transition opacity 1s
.fade-enter,
.fade-leave-to
opacity 0
fadeの部分が、transition(name="fade")
のnameと対応するようにします。
あとは、transitionのスタイルを当てる決まりに沿って、CSSを調整するだけです。
vue
export default {
data() {
return {
menus: [
{
flag: false,
title: 'メニュータイトル',
content: 'メニューコンテンツ',
},
{
flag: false,
title: 'メニュータイトル',
content: 'メニューコンテンツ',
},
{
flag: false,
title: 'メニュータイトル',
content: 'メニューコンテンツ',
},
{
flag: false,
title: 'メニュータイトル',
content: 'メニューコンテンツ',
},
{
flag: false,
title: 'メニュータイトル',
content: 'メニューコンテンツ',
},
],
}
},
methods: {
isOpen(key) {
this.menus[key].flag = !this.menus[key].flag
},
},
}
vueで定義しているのは、メニューのコンテンツの中身と表示非表示のフラグです。
あとは、表示と非表示を切り替える関数を設置しています。
表示の切り替え
methods: {
isOpen(key) {
this.menus[key].flag = !this.menus[key].flag
},
},
切り替えに必要な関数はこれだけです。
v-forで要素を繰り返し、表示しているのでkey
の取得を簡単にできるようになります。
なのでこの、key
を引数に渡し、どのメニューを表示させるかを判断します。
コレだけで簡単にアコーディオンメニューの実装ができます。
まとめ
今回の実装方法にはメリットもあれば、デメリットもあります。
参考程度にしていただけると良いかと思います。
メリット
- 簡単に実装できる
- メニューが増えるときは、dataを増やして上げるだけでいい
デメリット
- メニューの中身を表示充実させたときには使いにくい
- メニューの中身をdataで管理する必要がある
コメント