Vue.jsでjQueryの slideDown()とslideUp() 相当を行う方法
概要
jQueryの slideDown() / slideUp() の表示方法が気に入っていて、
Vue.jsでも出来ないかとやってみた、メモ書き。備忘録。
具体的には、次のように構成することで、実装する。for文で変化量を計算して適用とか不要。
-
v-if
ディレクティブで対象エリアの表示/非表示を切り替える。 -
transition
タグ+CSS3を用いて、表示/非表示の変化時を滑らかにする。
デモはこちら。⇒ Vue.jsでのアコーディオンメニュー例
なお、こういう「にょ~ん」と開いたり閉じたりするメニューを「アコーディオンメニュー」と呼ぶことがある、と今回に初めて知ったよ。「vue.js slideup() slidedown()」で検索してもイマイチ、これだ!ってのが見つからなくて、な。
なおなお、基本的にはCSSのtransition効果を用いた実現方法の様子。なので、CSSを理解している人なら悩まない実装なのかもしれない(当方、CSSは分からんので、ね)。
アコーディオンメニュー(slideDown/Up)の実装方法
次の順で、実装方法を説明する。
とりあえず動けばよい、って方は後半へ読み飛ばしOK。
-
v-if
ディレクティブで対象エリアの表示/非表示の実装する。 -
transition
タグを用いて、変化が瞬間ではなく連続的に起こるようCSSを適用する。
メニューの表示/非表示切り替え
これは、Vue.jsの v-if
を用いてそのまま実装するだけ。
デモ ※これは瞬間的に表示/非表示が切り替わる版。未だ目的の前段階。
<!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]
*/
.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]
*/
.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()相当の動作実装は完了ー。
デモ ※本節の冒頭のリンク先と同一。
<!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は全く分からんからなぁ、私は。この実装方法に辿り着くまで大分悩んだよ。。。
参考サイト
- Enter_Leave とトランジション一覧 — Vue.js (公式サイト)
- Vue.js-transition slideUp_slideDown
- Vue.jsで、スライドメニューを作る
- 【CSS3】Transition(変化)関連のまとめ - Qiita
- Vue.jsのトランジションとCSSで作るアニメーションの基本をサンプルでわかりやすく解説 – Nyle Engineering Blog