📈

【Vue.js】スライドアップダウン・ドロップダウン・アコーディオン

2021/07/11に公開

以前実装に使ったVueのライブラリについてメモ。
スライドアップダウンメニュー、ドロップダウンメニュー、アコーディオンメニューなど言い方がいろいろあるやつ。

今回の仕様

「詳しくはこちら」と書いてある赤色ヘッダーをクリックすると、

スライドがアニメーションで開き、詳細を表示する。周りの要素もスライドに合わせて移動する。

もう一度クリックすると元に戻る。

vue-slide-up-down

Vue.jsの開発で、スライド機能を実装するならvue-slide-up-downを使うと簡単に実装できた。
https://github.com/danieldiekmeier/vue-slide-up-down#readme

公式にはデモ実装もついているが自分用にもう少しシンプルにまとめる。
先に完成コードから。ちなみにコンポーネントファイルである。

components/Slide.vue
<template>
  <dl>
    <dt @click="isOpen" class="slideHead"> 
      <p class="headText">詳しくはこちら</p>
    </dt>
    <SlideUpDown :active="isActive">
      <dd class="slideBody">
        <p>This is vue-slide-up-down!</p>
      </dd>
    </SlideUpDown>
    <dd class="slideFoot">
      <p>★★★★</p>
    </dd>
  </dl>
</template>

<script>
import Vue from 'vue'
import SlideUpDown from 'vue-slide-up-down'

export default Vue.extend({
  data() {
    return {
      isActive: false,
    }
  },
  components: {
    SlideUpDown,
  },
  methods: {
    isOpen() {
      this.isActive = !this.isActive
    },
  }
})
</script>

<style>
/** スタイルはご自由に。見やすく整えたのみ。*/
.slideHead {
  height: 50px;
  width: 30%;
  margin-top: 30px;
  margin-left: 30px;
  background-color: #ea0069;
}
.headText {
  color: #0e0070;
  font-size: 20px;
  text-align: center;
}
.slideBody {
  height: 100px;
  width: 30%;
  margin-left: 30px;
  color: #FFFFFF;
  font-size: 20px;
  text-align: center;
  background-color: #0e0070;
}
.slideFoot {
  height: 30px;
  width: 30%;
  margin-left: 30px;
  color: #FFFFFF;
  font-size: 15px;
  text-align: center;
  background-color: #FFBBFF;
}
</style>

実装

インストールは以下の通り。

npm i vue-slide-up-down

<slide-up-down>タグをそのまま書いても実装できるが、今回は他のHTML要素と区別するためにライブラリはインポートしてエイリアスをつけてコンポーネント化しておく。ここではSlideUpDownと名付ける。

<script>
import Vue from 'vue'
import SlideUpDown from 'vue-slide-up-down'

export default Vue.extend({
  components: {
    SlideUpDown,
  },
})
</script>

次にHTMLを実装するが、ポイントはスライドが開いた時に表示させたい要素を、<SlideUpDown>タグの中に入れること。

<template>
  <dl>
    <dt>
      <p>詳しくはこちら</p>
    </dt>
    <SlideUpDown>
      <dd>
        <p>This is vue-slide-up-down!</p>
      </dd>
    </SlideUpDown>
    <dd>
      <p>★★★★</p>
    </dd>
  </dl>
</template>

次にscriptの実装。今回は<dt>要素をクリックするとすぐ下の<dd>要素が表示されるようにする。
<dt>要素をクリックするとisOpen()が実行され、isActiveプロパティのtrue/falseが切り替わる。固定設定して1回スライドが開いたらそのまま開けっ放しにすることも可能。

vue-slide-up-downでは4つのpropsを指定でき、このうちactive(type: Boolean)は必須で、<SlideUpDown>で囲った要素の表示/非表示を切り替えることができる。

<template>
  <dl>
    <dt @click="isOpen">
      <p>詳しくはこちら</p>
    </dt>
    <SlideUpDown :active="isActive">  <!-- activeを必ず指定 -->
      <dd>
        <p>This is vue-slide-up-down!</p>
      </dd>
    </SlideUpDown>
    <dd>
      <p>★★★★</p>
    </dd>
  </dl>
</template>

<script>
import Vue from 'vue'
import SlideUpDown from 'vue-slide-up-down'

export default Vue.extend({
  data() {
    return {
      isActive: false,  // 初期表示時は閉じている
    }
  },
  components: {
    SlideUpDown,
  },
  methods: {
    isOpen() {
      this.isActive = !this.isActive  // 何回でも開閉できる
      // this.isActive = true         // 1回開くとそのまま固定表示
    },
  }
})
</script>

これでスライド機能は完成。他のpropsは以下を指定できる。

duration(default: 500, type: Number)
スライドが開閉するアニメーション時間をミリ秒単位で設定できる。
tag(default: 'div', type: String)
公式には「ラッパー要素に使用するHTMLタグを設定できる」とあるが、ここでは<SlideUpDown>がWeb上でどの要素として扱われるのかを設定できる。
デフォルトでは<div>要素になるが、例えばtag="section"を指定すれば<SlideUpDown>は<section>要素として扱われる。

use-hidden(default: true, type: Boolean)
falseにするとhidden属性が適用されなくなる。
ユーザがキーボードやスクリーンリーダーを使っている場合、アクセシビリティの問題が発生する可能性があるので、設定には注意が必要とのこと。
大抵の場合はデフォルトのままでよいだろう。

まとめ

実際のWebページのコードはボリュームが多いので、スライド機能に関わる要素だけを抜き取ってまとめると案外シンプルだった。

ライブラリを使わずにスライドダウン機能を実装する場合はCSSも含めてアニメーション処理をゴリゴリ書いていけばできそうだが、メンテナンス面を考えるとシンプルに実装できる方がいい。

P.S.

これを読むとjQueryを書きたくなくなる&今後はもうVueでいいと思うようになった。jQueryからVueへの移行、SPAの概念を取り入れる流れはこれからまだまだ続くと思うので、Vueを極めておいて損はない。
https://blog.runteq.jp/programming-school/knowledge/2774/

Discussion