vue.jsで開閉式のメニューを作る

  • 2020年4月24日
  • 2024年1月28日
  • その他
  • 3323view

正社員で働きながらの副業に興味ある方はこちらの記事をご覧ください。

フルリモート週2~3日からでも副業が出来るエージェント紹介

 

はじめに

久々のVue.jsですが、今回は開閉式のメニューをコンポーネントで作っていきたいと思います。
下記の感じのクリックすると開いたり、閉じたりする感じのコンポーネントですね。

アコーディオンって呼ばれ方をする場合もあります。

 

 

vuetifyのv-selectの使い方は知りたい方はこちらの記事を読んで下さい

https://terrblog.com/v-select%e3%81%a7%e3%82%aa%e3%83%96%e3%82%b8%e3%82%a7%e3%82%af%e3%83%88%e3%82%92%e5%8f%96%e5%be%97%e3%81%99%e3%82%8b/

 

実装パート

 

HTML部分

 

以下のようなソースコードになります。
数字を振ってあるので、順番に解説していきます。

<template>
  <div class="profile-accordion">

//①見えている「てりー」の部分に@clickイベント//
    <div class="profile-title" @click="toggle">
      <p>てりー</p>
      <div class="base">
        <span class="down-arrow"></span>
      </div>
    </div>

//②transitionを使って動きを何パターンか指定//
    <transition
      v-on:before-enter="onBeforeEnter"
      v-on:enter="onEnter"
      v-on:bofore-leave="onBeforeLeave"
      v-on:leave="onLeave"
    >

//③v-showでクリック時のみ見えるようにする//
      <div v-show="show" class="accordion-wrapper">
        <div class="accordion-title -ly_contents">
          <p>メニュー</p>
        </div>
        <div class="accordion-contents -ly_contents">
          <ul>
            <li class="contents-list">基本情報</li>
            <li class="contents-list">パスワード</li>
            <li class="contents-list">メールアドレス</li>
          </ul>
        </div>
        <div class="bar -ly_contents"></div>
        <div class="accrodion-footer -ly_contents">
          <p>サインアウト</p>
        </div>
      </div>
    </transition>
  </div>
</template>

①@clickイベント

@clickはv-onの省略形です。
v-onで見えている部分をクリックするとtoggleというイベントが発火するようにしています。
toggleの処理はscriptの部分で書きます。

②transitionを指定

transitionでイベント時の動き方を指定しています。
transitionでは動きに対して、そのフェイズ毎に状態を指定することができます。

今回は以下の4パターンで指定しています。
具体的な状態はscriptにて記載しています。

 //要素の表示前
v-on:before-enter="onBeforeEnter"

//要素の表示中
 v-on:enter="onEnter"

//要素を閉じる前
 v-on:bofore-leave="onBeforeLeave"

//要素を閉じ中
 v-on:leave="onLeave"

③v-showにて表示・非表示切り替え

v-showで”show”状態なら括った要素を表示できるようにしています。
showがtrueかfalseかは@clickイベントのtoggleにて切り替えられるようにしています。

script部分

<script>
export default {
  name: "HelloWorld",

//①showの初期状態はfalseで閉じておく
  data() {
    return {
      show: false
    };
  },
  methods: {
//②toggleにてshowを切り替え
    toggle: function() {
      this.show = !this.show;
    },

//③transitionの各々での高さを指定
    onBeforeEnter: function(el) {
      el.style.height = 0;
    },
    onEnter: function(el) {
      el.style.height = "182px";
    },
    onBeforeLeave: function(el) {
      el.style.height = "182px";
    },
    onLeave: function(el) {
      el.style.height = 0;
    }
  }
};
</script>

①showの初期値

showの初期値はfalseで指定指定して、閉じています。

②toggleイベント

toggleイベントの処理に、showの切り替えを入れています。
これにより、クリックする度に表示・非表示が切り替わります。

③transitionの値の指定

先ほど出てきたtransitionの各フェイズでの具体的な値を指定しています。
今回は開いている時に高さが出て、閉じている時は高さ0になるようにしています。

css部分

style scoped>
.profile-accordion {
  height: 210px;
  width: 144px;
}
.profile-title {
  margin-left: 50px;
  height: 20px;
  display: flex;
}

.profile-title > p {
  margin: 0;
  height: 20px;
  width: 56px;
  color: #354052;
  font-family: "Noto Sans CJK JP";
  font-size: 14px;
  letter-spacing: 0;
  line-height: 20px;
}
.profile-title > .base {
  margin-top: 13px;
  margin-left: 6px;
}

.profile-title > .base > span {
  width: 0;
  height: 0;

  border-style: solid;
  border-width: 6px 4px 0 4px;
  border-color: #C5D0DE transparent transparent transparent;
}

.accordion-wrapper {
  position: relative;
  margin-top: 20px;
  margin-right: 80px;
  height: 182px;
  width: 140px;
  background-color: #FFFFFF;
  box-shadow: 0 0 4px 0 rgba(0, 0, 0, 0.3);
}

.accordion-wrapper::before {
  content: "";
  position: absolute;
  display: block;
  width: 0;
  height: 0;
  left: 100px;
  top: -10px;
  border-right: 10px solid transparent;
  border-bottom: 10px solid #C5D0DE;
  border-left: 10px solid transparent;
}

.accordion-wrapper::after {
  content: "";
  position: absolute;
  display: block;
  width: 0;
  height: 0;
  left: 100px;
  top: -8px;
  border-right: 10px solid transparent;
  border-bottom: 10px solid #FFFFFF;
  border-left: 10px solid transparent;
}

.-ly_contents {
  margin-left: 16px;
}

.accordion-title {
  padding: 20px 0 16px;
}
.accordion-title > p {
  color: #354052;
  font-family: "Noto Sans CJK JP";
  font-size: 14px;
  letter-spacing: 0;
  line-height: 18px;
  padding: 0;
  margin: 0;
  text-align: left;
}
.accordion-contents {
  display: block;
  padding: 0;
}

.accordion-contents > ul {
  text-align: left;
  padding: 0;
  margin: 0 0 10px;
}

.accordion-contents > ul > li {
  color: #354052;
  font-family: "Noto Sans CJK JP";
  font-size: 12px;
  letter-spacing: 0;
  line-height: 18px;
  list-style: none;
  margin-bottom: 8px;
}

.bar {
  height: 0.99px;
  width: 108px;
  background-color: #E0E6EF;
}
.accrodion-footer {
  padding: 0;
  text-align: left;
}

.accrodion-footer > p {
  color: #354052;
  font-family: "Noto Sans CJK JP";
  font-size: 12px;
  letter-spacing: 0;
  line-height: 18px;
  margin-bottom: 16px;
}
</style>

cssは形は作りましたが、汚いのであまり参考にしない方が良いです!笑
時間があるときに修正します。