【Vue】アコーディオンメニューを簡単に作る方法 (nuxt.js)

プログラミング

今回はアコーディオンメニューを簡単に実装できる方法について解説していきます。

今回は下記の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になり表示されるといった流れになります。

nuxt.jsにpugをインストールする方法
Nuxt.jsにpugをインストールする方法について解説します。

transition

transition(name="fade")
    .menu-content(v-if="menu.flag")
  

v-ifの値がfalseの状態だと、要素自体がない状態になっています。

このときに、アニメーションをつけるために、transitionを使います。

使い方についてはドキュメントに書いてあるのでそちらを参考にしてください。

Enter/Leave とトランジション一覧 — Vue.js
Vue.js - The Progressive JavaScript Framework

今回のアニメーションも公式のものを参考にしました。

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を調整するだけです。

nuxtにstylusをインストールする方法
もっとコーディングのスピードを上げたい、cssのコロンやセミコロン、{}、がめんどくさいなど思ったことはありませんか。stylusを入れてなれて来れば、コーディングのスピードは1.5倍早くなると思います。とう言うことで今回は、nu...

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で管理する必要がある
プログラミング
スポンサーリンク
スポンサーリンク
e-logsをフォローする
スポンサーリンク
eLogs

コメント

タイトルとURLをコピーしました