基礎からメモ: Vue.js CH6-p198 単一要素トランジション
<transition>
タグの中に1つだけ存在する要素に対し使用するものを「単一要素トランジション」と呼ぶ。
単一要素トランジションで使用するトランジションクラス
Enter系
とLeave系
の2つのフェーズがあり、それぞれ3種、計6種のクラスがある。
Enter系
は対象要素がDOMに追加されたときのフェーズ(表示時)、Leave系
は逆に対象要素がDOMから削除された時のフェーズ(非表示時)。
基本は追加時と削除時の次の2つの組合せ
- 追加時:
.v-enter
=>.v-enter-to
- 削除時:
.v-leave
=>.v-leave-to
他に.v-enter-active
と.v-leave-active
クラスがあり、それぞれEnter時とLeave時のアクティヴ状態を表す。
/* トランジション中に有効 */ .v-enter-active, .v-leave-active { transition: opacity 1s; } /* 表示される時 */ .v-enter { opacity: 1; } .v-enter-to { opacity: 1; } /* 消える時 */ .v-leave { opacity: 1; } .v-leave-to { opacity: 0; }
指定が何も無い場合はもともとopacity: 1
なので、.v-enter-to
と.v-leave
は省略でき、同じスタイルはまとめて次のように書ける。
/* 1秒かけて透明度を遷移 */ .v-enter-active, .v-leave-active { transition: opacity 1s; } /* 見えなくなるときの透明度 */ .v-enter, .v-leave-to { opacity: 0; }
Enter と Leave でスタイルを別にする
表示は左からフワッと現れ、消える時はフワッと下へ消える
/* 1秒かけて透明度を遷移 */ .v-enter-active, .v-leave-active { transition: opacity 1s, transform 1s; } /* 表示は左から */ .v-enter { opacity: 0; transform: translateX(-20px); } /* 消える時は下へ */ .v-leave-to { opacity: 0; transform: translateY(20px); }
複数の要素をグループ化
<transition>
タグの中に要素が複数あっても、描画結果が一つなら単一トランジションとして扱える。
<transition> <div v-if="show" key="a">TRUE</div> <div v-else key="b">FALSE</div> </transition>
この例の場合、TRUEとFALSEの切り替わり時に、表示がカクッとなっておかしいが、position:absolute
を片方のクラスに指定することで自然になる。
.v-leave-active { position: absolute; }
Enter と Leave のタイミングを変更する
トランジションは通常では Enter と Leave の処理を同時に行うが、mode
属性を付与することでタイミングを変更できる。
in-out
: Enterが終わってからLeaveを開始out-in
: Leaveが終わってからEnterを開始
<transition mode="out-in"> <div v-if="show" key="a">TRUE</div> <div v-else key="b">FALSE</div> </transition>
この例だとTRUE又はFALSEの表示が完全に消えてからもう一つの表示が始まる。(つまり2つの表示は全く重ならない)
これをin-out
にすると完全に次の表示がなされてから前のが消え始める(つまり一時的に2つの表示は重なる)。
特定のデータの変化でトランジションを発動させる
特定のデータの変化をトリガーとして、トランジションを発動させることもできる。
count
プロパティを要素のキーに設定し、ボタンを押してcount
の数値が変わるとそれをゆっくり表示する。
<div id="app"> <p><button v-on:click="count++">切り替え</button></p> <transition> <div v-bind:key="count">{{ count }}</div> </transition> </div>
var app = new Vue({ el: '#app', data: { count: 0 } });
.v-enter-active, .v-leave-active { transition: opacity 1s; } .v-leave-active { position: absolute; } .v-enter, .v-leave-to { opacity: 0; }
同じことをコンポーネントでやってみた例
<transition> <my-label v-bind:count="count" v-bind:key="count"></my-label> </transition>
Vue.component('my-label', { template: '<p>{{ count }}</p>', props: ["count"] }); var app = new Vue({ el: '#app', data: { count: 0 } });