When we build applications, we aim to make them easy on the eye. We want our users to have a smooth experience using it, and to feel our application flowing from one point to another, rather than just jump between screens.
If we switch components without transitions, we see a sharp change every time a new component is called up. This is not ideal and can result in our users having a poor experience with our application.
In this tutorial, we will look at how to improve the flow of our application using component transitions in Vue.
Prerequisites
- Vue CLI 3 for installing Vue
- Knowledge of JavaScript
- Knowledge of Vue.js
Setup Our Application
To begin, we will create a Vue application. Run the following command:
$ vue create component-transitions
$ cd component-transitions
Once we are done creating the application, we need to define a component we will use for the transitions.
Update The App Component
When we create a new Vue application, the CLI creates an App.vue
file inside the ./src
directory. Open the file and update the style
section as follows:
[...]
<style>
[...]
h3 {
margin: 40px 0 0;
}
ul {
list-style-type: none;
padding: 0;
}
li {
display: inline-block;
margin: 0 10px;
}
a {
color: #42b983;
}
</style>
We created global styles we wish to share across all our components. This way, we will not have to add styles per component again.
Update The HelloWorld Component
Our Vue application also comes with a HelloWorld.vue
file in located in ./src/components
directory. Open the file and edit as follows:
<template>
<div class="hello">
<h1>{{ msg }}</h1>
</div>
</template>
<script>
export default {
name: 'HelloWorld',
props: {
msg: String
}
}
</script>
Create The About Component
We are going to create a new component About.vue
inside the ./src/components
directory. Open the file and add the following:
<template>
<div>
<h1>{{ msg }}</h1>
</div>
</template>
<script>
export default {
name: 'About',
props: {
msg: String
}
}
</script>
Create Another Component
We are going to create another component Extra.vue
inside the ./src/components
directory. Open the file and add the following:
<template>
<div>
<h1>{{ intro }}</h1>
</div>
</template>
<script>
export default {
name: 'Extra',
props: {
msg: String
},
data(){
return {
intro : "Extra"
}
},
watch: {
msg : {
immediate: true,
handler(val, oldval) {
//
}
}
}
}
</script>
For our extra component, we have added a watch method to track the updates to the msg
prop. When the message prop updates, we want to update the intro
property.
We defined it this way to allow us to use transitions on the component.
Rendering Our Components
Vue provides a variety of ways to apply transition effects when items in a component are updated or when components themselves are changed. It ranges from applying CSS classes for transitions and animations to using 3rd party JavaScript libraries for transition effects.
The first set of transitions we will define will be on change of components. We will use conditional rendering to display the components we created and apply transition as they render.
Import The Components
We need to import the components we created into our App.vue
component. Open the file and edit as follows:
[...]
<script>
import HelloWorld from './components/HelloWorld.vue'
import About from './components/About.vue'
import Extra from './components/Extra.vue'
export default {
name: 'app',
components: {
HelloWorld, About, Extra
}
}
</script>
Use The Components
Now that we have imported the components, let us use it in our App
component. Edit the App.vue
file as follows:
<template>
<div id="app">
<img src="./assets/logo.png">
<HelloWorld msg="Welcome to your Vue.js application"/>
<Extra :msg="extra"/>
<About msg="This is the About page"/>
<button @click="changeExtra">Update Extra</button>
</div>
</template>
We defined a function changeExtra
to listen for button clicks and also bound the msg
prop for the Extra
component to extra
attribute. Now, let’s create the extra
attribute and changeExtra
method. We will just leave the Vue.js logo there so the page doesn’t feel empty ?
Edit the file as follows:
[...]
export default {
name: 'app',
components: {
HelloWorld, About, Extra
},
data(){
return {
extra : "Extra"
}
},
methods : {
changeExtra(){
this.extra = "This is extra"
}
},
}
[...]
Define Links For Switching Components
We are going to show one component at a time. To do this, we will have a simple set of links that would allow us to state which component to use at a certain time.
Open the App.vue
file and add the following:
<template>
<div id="app">
[...]
<div>
<ul>
<li @click="showHome">Home</li>
<li @click="showAbout">About</li>
<li @click="showExtra">Extra</li>
</ul>
</div>
</div>
</template>
Then add the methods we used above:
[...]
methods : {
[...]
showHome(){
this.displayHome = true
this.displayAbout = false
this.displayExtra = false
},
showAbout(){
this.displayHome = false
this.displayAbout = true
this.displayExtra = false
},
showExtra(){
this.displayHome = false
this.displayAbout = false
this.displayExtra = true
}
},
[...]
Finally, we define the properties — displayHome
, displayAbout
, displayExtra
.
[...]
data(){
return {
extra : "Extra",
displayHome : true,
displayAbout : false,
displayExtra : false
}
},
[...]
We set displayHome
to true so that anytime we load our application, it shows up first. The rest is false so they do not show up.
Conditional Rendering Of Our Components
Now that we have defined links for showing our components, let’s render them based on certain conditions.
Still in the App.vue
file, edit it as follows:
<template>
<div id="app">
<img src="./assets/logo.png">
<HelloWorld msg="Welcome to your Vue.js application" v-if="displayHome"/>
<About msg="This is the About page" v-if="displayAbout"/>
<div v-if="displayExtra">
<Extra :msg="extra"/>
<button @click="changeExtra">Update Extra</button>
</div>
[...]
</div>
</template>
So, we have completely rendered all of our components, now we can add transitions to it. Hurray!!!
Defining Transitions On Data Change
We will modify Extra
component. We want to add a simple transition effect when we update the data inside of it. Open the Extra.vue
file in the ./src/components/
directory and edit as follows:
<template>
<div>
<transition name="fade">
<h1 v-if="!msg">{{ intro }}</h1>
</transition>
<transition name="fade">
<h1 v-if="msg">{{ msg }}</h1>
</transition>
</div>
</template>
[...]
<style scoped>
.fade-enter-active{
transition: opacity 1.5s;
}
.fade-leave-active {
opacity: 0;
}
.fade-enter, .fade-leave-to {
opacity: 0;
}
</style>
This is a simple component. When we click the Update Extra
button, we will notice a slide fading transition occur. The transition is very noticeable, so our users must see it.
We are able to achieve the transition by wrapping our element in a Vue transition element and then defining the effect we want the transition element to use. In our case, we used opacity to make the component appear and disappear.
For data change transitions, you might want to use state transition as it provides a more robust experience. Read more about State Transitions.
Vue provides hooks at different stages of the transition cycle that we can hook into and define how we want the transition to be. I’ve added an image below from Vue.js website to illustrate this:
v
represents the name of our transition. In the case of the Extra
component, we replace v
with fade
to have fade-enter
in place of v-enter
and so on.
Defining Transitions On Component Change
Define Transition On The HelloWorld Component
Now, to the App
component where we will explore different other ways to implement transitions. Let’s define the transition on the HelloWorld
component. Open the App.vue
file and edit as follows:
<transition name="welcome">
<HelloWorld msg="Welcome to your Vue.js application" v-if="displayHome"/>
</transition>
Our transition will be named “welcome”. Now, add the transition classes to get your desired effect:
<style scoped>
/* Welcome Styles */
.welcome-enter {
transform: translateX(10px);
opacity: 0;
}
.welcome-enter-active {
transition: all .8s cubic-bezier(1.0, 0.5, 0.8, 1.0);
}
.welcome-leave-active, .welcome-leave-to {
opacity: 0;
}
</style>
Now, every time we click the Home
link, there will be a little shaking ? as our component it shows.
PS: We created a new
style
element and added ‘scoped` to it.
Define Transition On The About Component
We will take a similar step with what we did for the HelloWorld
component. Open the file and add the following:
[...]
<transition name="about">
<About msg="This is the About page" v-if="displayAbout"/>
</transition>
[...]
Then add the transition effect:
<style scoped>
[...]
/* About Styles */
.about-enter {
width: 30%;
opacity: 0;
}
.about-enter-active {
transition: all 2s ease-in-out;
}
.about-leave-active, .about-leave-to {
opacity: 0;
}
.about-enter-to {
width:100%;
opacity: 1;
margin-left: auto;
}
</style>
Define The Transition On Extra Component
Finally, let’s also add a transition for enter and exit of the extra component:
[...]
<transition name="extra">
<div v-if="displayExtra">
<Extra :msg="extra"/>
<button @click="changeExtra">Update Extra</button>
</div>
</transition>
[...]
Then add the styles for the transition:
<style scoped>
[...]
/* Extra Styes */
.extra-enter {
transform: translateX(-200px);
opacity: 0;
}
.extra-enter-to {
transform: translateX(0px);
}
.extra-enter-active {
transition: all 1s cubic-bezier(1.0, 0.5, 0.8, 1.0);
}
.extra-leave-active, .extra-leave-to {
opacity: 0;
}
</style>
And that’s it for component transitions.
Run The Application
Now that we are done defining transitions for our various components, let’s run the application and see what it looks like.
From your terminal, run the following command:
$ npm run serve
Then visit the application on the url that appears.
See A Demo
Conclusion
We have looked at vue component transitions in this tutorial. We saw how easy it is to add transitions to our application. I have to admit we kind of overdid the transition thing and used effects we may not want to use in a real application. The entire goal was to show that anything is possible.
Try to use different CSS transitions for your components and see what you can come up with.
Source: Scotch.io