JavaScript
Vue.js

Vue.jsでjQueryの slideDown()とslideUp() 相当を行う方法

Vue.jsでjQueryの slideDown()とslideUp() 相当を行う方法


概要

jQueryの slideDown() / slideUp() の表示方法が気に入っていて、

Vue.jsでも出来ないかとやってみた、メモ書き。備忘録。

結論から言うと、Vue.jsの標準機能の範囲で出来る

スクリーンショット 2019-03-20 12.26.49.png

具体的には、次のように構成することで、実装する。for文で変化量を計算して適用とか不要



  • v-if ディレクティブで対象エリアの表示/非表示を切り替える。


  • transition タグ+CSS3を用いて、表示/非表示の変化時を滑らかにする。

デモはこちら。⇒ Vue.jsでのアコーディオンメニュー例

なお、こういう「にょ~ん」と開いたり閉じたりするメニューを「アコーディオンメニュー」と呼ぶことがある、と今回に初めて知ったよ。「vue.js slideup() slidedown()」で検索してもイマイチ、これだ!ってのが見つからなくて、な。

なおなお、基本的にはCSSのtransition効果を用いた実現方法の様子。なので、CSSを理解している人なら悩まない実装なのかもしれない(当方、CSSは分からんので、ね)。


アコーディオンメニュー(slideDown/Up)の実装方法

次の順で、実装方法を説明する。

とりあえず動けばよい、って方は後半へ読み飛ばしOK。



  1. v-if ディレクティブで対象エリアの表示/非表示の実装する。


  2. transition タグを用いて、変化が瞬間ではなく連続的に起こるようCSSを適用する。


メニューの表示/非表示切り替え

これは、Vue.jsの v-if を用いてそのまま実装するだけ。

デモ ※これは瞬間的に表示/非表示が切り替わる版。未だ目的の前段階。


accordion_slide_menu0.html

<!DOCTYPE html>

<html>
<head>
<title>アコーディオンメニュー/SlideUp(), SlideDown()</title>

<meta charset="UTF-8" />
<!-- Font Awesome を利用 -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" integrity="sha384-wvfXpqpZZVQGK6TAh5PVlGOfQNHSoD2xbE+QkPxCAFlNEevoEH3Sl0sibVcOQVnN" crossorigin="anonymous"></link>

<!-- CDN の vue.js を利用 -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.4.2/vue.min.js"></script>

<!-- transitionにはCSS必須 -->
<link rel="stylesheet" href="accordion_slide_menu.css"></link>
</head>
<body>

<div id="vue_slideupdown">
<!-- vuejs-slidemenu -->
<div class="cls_toggle_expand_collapse" v-on:click="toggleCtrlPanel">
<i class="fa fa-caret-down" v-if="isPanelShow"></i>
<i class="fa fa-caret-right" v-if="!isPanelShow"></i>
{{textToggle}}
</div>
<div class="menu_slide_accordion" v-if="isPanelShow">
slideUp(), slideDown() したい内容を任意に書く。<br>
純粋なhtmlでも良いし、<br>
Vueの要素を書いても良い。<br>
</div>
<div>
デモ。<br>
<br>
その他の要素。<br>
この部分は、上部のメニューの開閉に伴ってアップダウンする。<br>
※こちらは「スライドアップ、スライドダウンの効果無し版」
</div>
</div>

<!-- サンプルなので、簡便を目的にhtml内に記述 -->
<script>
var vueAccordion = new Vue({
el:"#vue_slideupdown",
data: {
textToggle: "開閉するトグル(ここを押す)",
isPanelShow: false
},
methods:{
toggleCtrlPanel: function () {
this.isPanelShow = !this.isPanelShow;
}
}
})
</script>
</body>
</html>


表示切替するエリアに適用するCSSは以下のようにしておく。なお、CSSで表示サイズを指定しておかないと、あとでSlideDown()/Up()相当を実装するときに上手く行かないので注意。※縦サイズのみが変化対象なので、縦サイズが指定されていれば良い。


accordion_slide_menu.css

/*

* [accordion_slide_menu.css]
*/

.cls_toggle_expand_collapse {
margin : 4px;
padding : 8px;
cursor : pointer;
background-color: aquamarine
}

/*
* Slide / accordionメニューの設定
*/

.menu_slide_accordion {
background-color: antiquewhite;
height: 120px;
overflow: hidden;
}



表示時の変化を連続的にする

上記の表示/非表示を切り替えに緩やかな時間変化を付ける。

デモ

これを行うには、先ず表示/非表示を切り替えるエリアである <div class="menu_slide_accordion" v-if="isPanelShow"> の部分を、

transition タグで次のように囲む。

<transition name="trans_slide">

<div class="menu_slide_accordion" v-if="isPanelShow">
slideUp(), slideDown() したい内容を任意に書く。<br>
純粋なhtmlでも良いし、<br>
Vueの要素を書いても良い。<br>
</div>
</transition>

すると、「囲んだ要素内のDOMが追加、更新、削除したときにトランジション効果を適用」することが容易にできる。具体的には次のように「transitionタグのname属性名+-xxxx」というクラス指定を用いて「変化の仕方」と「変化させるパラメータ」を指定する。

/* Vueの方で自動的に付与されるクラス::-enter-xx */

.trans_slide-enter-active, .trans_slide-leave-active {
transition: opacity .5s;
}
.trans_slide-enter, .trans_slide-leave-to {
opacity: 0;
}

上記のCSS表記例は、次ような「変化」を指定する内容。動作としては「挿入時に、1秒をかけて透明から不透明に変化する」+「削除人、1秒をかけて不透明から透明に変化する」というアニメーションになる。


  • DOMが挿入されようとしたら(xxx-enter)、「opacity = 0」に設定する。

  • DOM挿入後の状態に向かって、opacity属性を、5sの時間をかけて変化させる。


    • ここで「挿入後」とは「表示が完了した」状態なので、「opacity = 1」を意味する。

    • この「〇〇属性を、xxの時間をかけて変化させる」はCSS3の transition 機能そのもの。この例であれば「変化中(xxx-enter-active)は transition: opacity .5s に従う」という設定の仕方となる。



  • DOMが削除されたら(xxx-leave-to)、「opacity = 0」に設定する。

  • DOM削除後の状態に向かって、opacity属性を、5sの時間をかけて変化させる。


    • ここで「削除後」の状態として「opacity = 0」の状態を指定しているので、この変化の開始前の「opacity = 1」に対して「1→0」と変化させることを意味する。

    • 削除へ向かう変化中(xxx-leave-active)の変化の仕方は、同様にCSS3の transition 機能で指定する。



透明度を変化させる代わりに、次のようにheight属性値の変化を指定することで「にょ~ん、と上から下へ開く。しゅるる~、と下から上へ閉じる」というslideDown(), slideUp() 相当のアニメーション動作を実装できる

/* Vueの方で自動的に付与されるクラス::-enter-xx */

.trans_slide-enter-active, .trans_slide-leave-active {
transition: all .5s;
}
.trans_slide-enter, .trans_slide-leave-to {
height: 0;
}

slideDown(), slideUp() 相当の動作を設定したCSSファイルの全体像は、次のようになる。

ここで、変化対象とするdivクラスのwidth属性の初期値(挿入時=表示時の初期値)を明記することを忘れずに。さもないと変化の向かう先が見つからず、上手くアニメーションにならない。それから、「overflow: fidden;」を指定しておくことで「高さが小さくなったdiv要素からはみ出したテキストを表示しない」設定にすることを忘れずに。これを設定しないと、divの動作から置いて行かれてはみ出したテキストが残り、見た目がイマイチになる。


accordion_slide_menu.css

/*

* [accordion_slide_menu.css]
*/

.cls_toggle_expand_collapse {
margin : 4px;
padding : 8px;
cursor : pointer;
background-color: aquamarine
}

/*
* Slide / accordionメニューの設定
*/

.menu_slide_accordion {
background-color: antiquewhite;
height: 120px;
overflow: hidden;
}
/* Vueの方で自動的に付与されるクラス::-enter-xx */
.trans_slide-enter-active, .trans_slide-leave-active {
transition: all .5s;
}
.trans_slide-enter, .trans_slide-leave-to {
height: 0;
}


transition タグを追加した、htmlコード全体は次のようになる。メニューを開閉するjavascriptコード側の変更は不要。これで、アコーディオンメニュー/SlideUp(), SlideDown()相当の動作実装は完了ー。

デモ ※本節の冒頭のリンク先と同一。


accordion_slide_menu.html

<!DOCTYPE html>

<html>
<head>
<title>アコーディオンメニュー/SlideUp(), SlideDown()</title>

<meta charset="UTF-8" />
<!-- Font Awesome を利用 -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" integrity="sha384-wvfXpqpZZVQGK6TAh5PVlGOfQNHSoD2xbE+QkPxCAFlNEevoEH3Sl0sibVcOQVnN" crossorigin="anonymous"></link>

<!-- CDN の vue.js を利用 -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.4.2/vue.min.js"></script>

<!-- transitionにはCSS必須 -->
<link rel="stylesheet" href="accordion_slide_menu.css"></link>
</head>
<body>

<div id="vue_slideupdown">
<!-- vuejs-slidemenu -->
<div class="cls_toggle_expand_collapse" v-on:click="toggleCtrlPanel">
<i class="fa fa-caret-down" v-if="isPanelShow"></i>
<i class="fa fa-caret-right" v-if="!isPanelShow"></i>
{{textToggle}}
</div>
<transition name="trans_slide">
<div class="menu_slide_accordion" v-if="isPanelShow">
slideUp(), slideDown() したい内容を任意に書く。<br>
純粋なhtmlでも良いし、<br>
Vueの要素を書いても良い。<br>
</div>
</transition>
<div>
デモ。<br>
<br>
その他の要素。<br>
この部分は、上部のメニューの開閉に伴ってアップダウンする。<br>
</div>
</div>

<!-- サンプルなので、簡便を目的にhtml内に記述 -->
<script>
var vueAccordion = new Vue({
el:"#vue_slideupdown",
data: {
textToggle: "開閉するトグル(ここを押す)",
isPanelShow: false
},
methods:{
toggleCtrlPanel: function () {
this.isPanelShow = !this.isPanelShow;
}
}
})
</script>
</body>
</html>


以上ー。


蛇足

感想など。

CSS3のtransition属性を知っていれば、悩まない話だったポイ。CSSは全く分からんからなぁ、私は。この実装方法に辿り着くまで大分悩んだよ。。。


参考サイト