Vue-router page loading effect

Jilson Thomas
VueJobs
Published in
4 min readOct 26, 2016
Vue-router page loading effect

If you are building a Single Page Application (SPA) using vue-router and APIs, you are most likely dealing with vue components. Each page will be vue component. So, when you load each page, you’ll have to wait for the API to get the result from the server in order for vue to render the page.

Let’s just take take the example of a user profile page.

Our user.vue would look like this:

<template>
<div>
<h2 v-text="user.name"></h2>
<p v-text="user.description"></p>
</div>
</template>
<script>
export default{
data(){
return{
user: {}
}
}
}
</script>

We’ll fetch the data from the server during the transition as below:

<script>
export default{
data(){
return{
user: {}
}
},
route: {
data: function (transition) {
this.getUserDetails(transition);
}
},

methods: {

getUserDetails(transition)
{
this.$http.get('/users/' + this.$route.params.userName)
.then(function (response) {
this.user = response.data;
transition.next();
});

}
}
}
</script>

So in this case, we have access to a variable $loadingRouteData

You’ll be able to hide all your page elements and show a loader just like facebook or medium itself.

<div v-if="$loadingRouteData">
<div class="white-widget grey-bg author-area">
<div class="auth-info row">
<div class="timeline-wrapper">
<div class="timeline-item">
<div class="animated-background">
<div class="background-masker header-top"></div>
<div class="background-masker header-left"></div>
<div class="background-masker header-right"></div>
<div class="background-masker header-bottom"></div>
<div class="background-masker subheader-left"></div>
<div class="background-masker subheader-right"></div>
<div class="background-masker subheader-bottom"></div>
</div>
</div>
</div>
</div>
</div>
</div>
<div v-if="!$loadingRouteData">
<div>
<h2 v-text="user.name"></h2>
<p v-text="user.description"></p>
</div>
</div>

and for the facebook/medium like loading effect, use the following CSS

.timeline-item {
background: #fff;
border-bottom: 1px solid #f2f2f2;
padding: 25px;
margin: 0 auto;
}

@keyframes placeHolderShimmer{
0%{
background-position: -468px 0
}
100%{
background-position: 468px 0
}
}

.animated-background {
animation-duration: 1s;
animation-fill-mode: forwards;
animation-iteration-count: infinite;
animation-name: placeHolderShimmer;
animation-timing-function: linear;
background: #f6f7f8;
background: linear-gradient(to right, #eeeeee 8%, #dddddd 18%, #eeeeee 33%);
background-size: 800px 104px;
height: 40px;
position: relative;
}

.background-masker {
background: #fff;
position: absolute;
}

/* Every thing below this is just positioning */

.background-masker.header-top,
.background-masker.header-bottom,
.background-masker.subheader-bottom {
top: 0;
left: 40px;
right: 0;
height: 10px;
}

.background-masker.header-left,
.background-masker.subheader-left,
.background-masker.header-right,
.background-masker.subheader-right {
top: 10px;
left: 40px;
height: 8px;
width: 10px;
}

.background-masker.header-bottom {
top: 18px;
height: 6px;
}

.background-masker.subheader-left,
.background-masker.subheader-right {
top: 24px;
height: 6px;
}


.background-masker.header-right,
.background-masker.subheader-right {
width: auto;
left: 300px;
right: 0;
}

.background-masker.subheader-right {
left: 230px;
}

.background-masker.subheader-bottom {
top: 30px;
height: 10px;
}

.background-masker.content-top,
.background-masker.content-second-line,
.background-masker.content-third-line,
.background-masker.content-second-end,
.background-masker.content-third-end,
.background-masker.content-first-end {
top: 40px;
left: 0;
right: 0;
height: 6px;
}

.background-masker.content-top {
height:20px;
}

.background-masker.content-first-end,
.background-masker.content-second-end,
.background-masker.content-third-end{
width: auto;
left: 380px;
right: 0;
top: 60px;
height: 8px;
}

.background-masker.content-second-line {
top: 68px;
}

.background-masker.content-second-end {
left: 420px;
top: 74px;
}

.background-masker.content-third-line {
top: 82px;
}

.background-masker.content-third-end {
left: 300px;
top: 88px;
}

That’s it. You now have an amazing vue-router loader. You can even make it as a separate component and use it anywhere you like. I’ll show you how to use it in another article.

Closing

This is just a simple tutorial for the vue-router component loading and we can optimize it in many ways. Next one would be the content-loader vue component that you can reuse in all places.

VueJobs.com

If you are a Vue.js developer and looking for a job, subscribe to our mailing list. Or if you are looking for a Vue.js developer, feel free to post your job requirements here in vuejobs.com.

VueJobs.com
VueConfTO 2018 | 14–16 November 2018 | Fairmont Royal York Toronto

--

--

Jilson Thomas
VueJobs

UI/UX Engineer, Laravel Developer with huge passion for Vue.js