How to show a loading icon before data is loaded in Vue and Vuex
UPDATE: I have a better way of handling this here. I would recommend that post if you’re looking to handle the status of your data loads from now on.
I hate ambiguous lag. Is this site still loading or did it freeze? Am I waiting for something or is this it? Whenever a website has to load in information from an API, there is a chance that loading will appear painfully slow to the user. Human beings perceive an empty screen much differently than they perceive an animation on the screen.1 In order to make our website seem faster than it is, it’s always good to throw in a loading animation every time that we have to access a potentially slow resource like an API call.
Applications built in Vue have this same issue, but Vue gives us a number of tools to handle this very gracefully. This article will show a way to handle loading icons that make showing and hiding the icons very simple. If you’re following the methods for loading data from APIs that I laid out in How to query your API using Vuex in your Vue application that will make this even easier.
Getting a loading icon
First step is to get a loading icon for your site. I downloaded one from Preloaders.net - Circular (Spinners). I made this one for this exercise:
I’ll be using an svg spinner, but you can use whatever icon you want that is supported by the browsers you’re targeting.
Adding the icon to the component
To add the icon to the component, we can just add a v-show
to the location where the data we are loading in will be located. Before the data is loaded, we will show the spinner. Once the data is loaded, we can hide the spinner and show the data table.
In my example below, I’m using the user table that I showed off in the article on loading data via an API into Vuex.
You can look at the code for this example at https://codesandbox.io/s/using-loading-icons-in-vuex-36jh6
In the Vuex store, we defined the initial state of the users
array to be an empty array:
state: {
users: []
},
If the users
state variable is empty, then that means we haven’t loaded in the data yet. So we can set up our UI in our component like this:
<div v-show="users.length == 0">
<img src="./../assets/loading icon.png">
</div>
<table class="users" v-show="users.length != 0">
<tr>
<th>Name</th>
<th>Username</th>
<th>Email</th>
</tr>
<tr v-for="user in users" v-bind:key="user.id">
<td>{{user.name}}</td>
<td>{{user.username}}</td>
<td>{{user.email}}</td>
</tr>
</table>
So if the users
data property is empty, show the loading icon. Otherwise, show the table. And once we map in the users
state variable from Vuex:
computed: {
users() {
return this.$store.state.users;
}
},
Then the loading icon will show up before the data can be loaded. This goes a long way in letting a user know that we’ve got this handled. They can see that we have anticipated that this data may take time to load and that they just need to wait a hot second before the table will show up.
This is great if the data load is being called from a created()
method, but what if the user requests a reload of the data or you need to otherwise pull data from the server again?
One thing you can do is to blank out the users
state variable by calling this.$store.commit('SAVE_USERS', []);
. This will again show the loading icon and then you can call this.$store.dispatch("loadUsers");
again to get the new data.
This is a very easy way to show a loading icon for users. It might not work for every situation you have, but covers a lot of the common use cases that front-ends have for letting the user know that a data load is in progress.
- For more interesting information on human perception of time and web applications, take a look at this Smashing article: Why Performance Matters, Part 2: Perception Management — Smashing Magazine [return]