Javascript is required
ยท
1 min read

Vue Tip: Animate Child Component Before Route Leave

Vue Tip: Animate Child Component Before Route Leave Image

Vue Router provides a way to use transitions on your route components and animate navigations.

But sometimes, you might want to animate a specific (sub-)component before a route is left.

Therefore, you can use the onBeforeRouteLeave navigation guard combined with a ref to toggle the visibility of the component:

Info

The v-if is necessary to trigger the animation. More at the official docs.

1<template>
2  <section class="body">
3    <Transition name="image">
4      <img v-if="showUI" src="../assets/image.svg" alt="Image" />
5    </Transition>
6  </section>
7</template>
8
9<script setup lang="ts">
10import { ref } from 'vue'
11import { onBeforeRouteLeave } from 'vue-router'
12
13const showUI = ref(true)
14
15onBeforeRouteLeave((to, from, next) => {
16  if (to.name === 'Home') {
17    showUI.value = false
18    setTimeout(() => {
19      next()
20    }, 1000)
21  } else {
22    next()
23  }
24})
25</script>
26
27<style lang="scss">
28.image-leave-active {
29  transition: transform 1s ease;
30}
31
32.image-leave-to {
33  transform: translateY(30vw) translateX(40vw) rotate(30deg);
34}
35</style>

Let's take a closer look at the code inside onBeforeRouteLeave:

1onBeforeRouteLeave((to, from, next) => {
2  if (to.name === 'Home') {
3    showUI.value = false
4    setTimeout(() => {
5      next()
6    }, 1000)
7  } else {
8    next()
9  }
10})

If the following route is anything other than Home, we allow the navigation and call next.

If the following route is Home, we toggle the component's visibility by setting showUI to false. Next, we call setTimeout with 1 second to wait until the animation is done and then proceed with the route change by calling next.

The animation time is defined in our <style> block:

1<style lang="scss">
2.image-leave-active {
3  transition: transform 1s ease;
4}
5
6.image-leave-to {
7  transform: translateY(30vw) translateX(40vw) rotate(30deg);
8}
9</style