Unlikenesses A Backend Developer

vue transitions

21 June 2017

To fade between pages in vue-router is pretty simple. The transition component can be used to wrap the router-view component. But there's a slight issue. If we use it as in the example, the page transitions look a little janky:

<transition name="fade">
    <router-view></router-view>
</transition>

CSS:

.fade-enter-active, .fade-leave-active {
    transition: opacity .5s
}

.fade-enter, .fade-leave-to {
    opacity: 0
}

This is because the default behaviour when transitioning between two elements is to perform both transitions simultaneously. This is where transition modes come into play. Using the out-in mode the first page will completely fade out before the new one fades in:

<transition name="fade" mode="out-in" appear>

Finally, adding the appear attribute, as above, means that the transition is applied to the first page when it loads (docs).

Issue: the transition is not applied to routes using dynamic route matching. E.g. there is no transition between /post/1 and /post/2. My guess is that this is because, as the manual says:

when the user navigates from /user/foo to /user/bar, the same component instance will be reused.

The solution (following this StackOverflow answer, thanks!) is to wrap the contents of the page in a div with a specific key value (in this example based on the route parameter) and wrap that in the transition tag:

<transition name="fade" mode="out-in" appear>
    <div class="page-contents" :key="$route.params.id">
        <!-- component code here -->
    </div>
</transition>