Vue.jsのtransitionでJavaScriptフックを使ってより複雑なアニメーションを適用する
Vue.jsのtransitionでJavaScriptフックを使ってより複雑なアニメーションを適用する方法を紹介します。
JavaScriptフック
enterのhooksには、次のような段階があります。
before-enter
enter
after-enter
leaveのhooksには、次のような段階があります。
before-leave
leave
after-leave
公式サイトでは、cancelledも含めて8つが紹介されています。
<transition
v-on:before-enter="beforeEnter"
v-on:enter="enter"
v-on:after-enter="afterEnter"
v-on:enter-cancelled="enterCancelled"
v-on:before-leave="beforeLeave"
v-on:leave="leave"
v-on:after-leave="afterLeave"
v-on:leave-cancelled="leaveCancelled"
>
<!-- ... -->
</transition>
JavaScriptフックを定義したtransitionの使い方
<transition
appear
name="fade"
@before-enter="beforeEnter"
@enter="enter"
@after-enter="afterEnter"
@before-leave="beforeLeave"
@leave="leave"
@afterLeave="afterLeave"
>
<h1 v-if="showTitle">About</h1>
</transition>
v-onを使って、""のところはJavaScriptなのでキャメルケースを使います。
たとえばshowTitleという変数を用意して、true/falseでタイトルを表示・非表示できるようにするとします。
import { ref } from '@vue/reactivity';
export default {
setup() {
const showTitle = ref(true)
return {
showTitle,
}
}
}
そして、JavaScriptのフックをそれぞれ定義していきます。
import { ref } from '@vue/reactivity';
export default {
setup() {
const showTitle = ref(true)
const beforeEnter = (el) => {
console.log('beforeEnter', el);
}
const enter = (el) => {
console.log('Enter', el);
}
const afterEnter = (el) => {
console.log('afterEnter', el);
setTimeout(() => showTitle.value = false, 3000)
}
const beforeLeave = (el) => {
console.log('beforeLeave', el);
}
const leave = (el) => {
console.log('Leave', el);
}
const afterLeave = (el) => {
console.log('afterLeave', el);
}
return {
showTitle,
beforeEnter,
enter,
afterEnter,
beforeLeave,
leave,
afterLeave,
}
}
}
上のように、それぞれコンソールに出力してみると、タイミングが目に見えてわかってtransitionを設定しやすくなります。
また、elとした要素を出力することで、classがそれぞれ変化していることがわかります。
上の例では、afterEnterのときだけ、titleが非表示になるように設定してあります。
引数に渡される要素を操作する
引数には要素が渡されます。
そのため、それを使うことができるため、あとはJavaScriptでcssを操作することが可能になります。
具体例では、styleにアクセスして、colorやbackgroundColorなど変えたいものにアクセスして変えたいものを設定するというシンプルな使い方が可能になります。
const afterEnter = (el) => {
el.style.backgroundColor = 'green'
console.log('afterEnter', el);
setTimeout(() => showTitle.value = false, 3000)
}