Hiding vue.js template before it is rendered
I'm just adding a useful things of v-cloak to add a spinner before rendering the full HTML file and thanks to Adam for his Gist - https://gist.github.com/adamwathan/3584d1904e4f4c36096f
If you want to add a spinner before loading your page, you can read this -
- Add
v-cloak
inside#app
. - Make one div
v-cloak--inline
which we want to show before HTML page rendered. - Another Div which will contain the full page with
v-cloak--hidden
. - Must have to add the css's given here.
Let's code - In Master Page,
<div id="app">
<div v-cloak>
<div class="v-cloak--inline"> <!-- Parts that will be visible before compiled your HTML -->
<i class="fa fa-spinner fa-pulse fa-3x fa-fw"></i>
<span class="sr-only">Loading...</span>
</div>
<div class="v-cloak--hidden"> <!-- Parts that will be visible After compiled your HTML -->
<!-- Rest of the contents -->
@yield('content')
</div>
</div>
</div>
With adding these Extra CSS's for v-cloak.
[v-cloak] .v-cloak--block {
display: block;
}
[v-cloak] .v-cloak--inline {
display: inline;
}
[v-cloak] .v-cloak--inlineBlock {
display: inline-block;
}
[v-cloak] .v-cloak--hidden {
display: none;
}
[v-cloak] .v-cloak--invisible {
visibility: hidden;
}
.v-cloak--block,
.v-cloak--inline,
.v-cloak--inlineBlock {
display: none;
}
Then Before compiling the HTML file, a spinner will render. After compiled, spinner will hide. You can use this in your master page. Thus in every time when you load a new page, that will see the effects.
See the Gist - https://gist.github.com/adamwathan/3584d1904e4f4c36096f
By adding v-cloak to whole page root div will work
<div id="app">
<div v-cloak>
Hello {{ name }}
</div>
</div>
<style>
[v-cloak] {
display: none;
}
</style>
Hide elements during loading using "v-cloak"
I would hesitate to mix jQuery in Vue.js code for the reason that Vue.js provides a suite of tools that generally eliminate the need for jQuery.
Since you are loading the page and displaying a progress bar, you can take advantage of the Vue.js lifecycle hooks: [created, mounted, beforeUpdate, updated, etc. etc.].
What I would do is to create a small div containing the progress bar, and then an adjacent element with the actual content to display after load. Set a data on the component instance, and then use the lifecycle hooks to toggle the display.
<div v-if='loading'>
<div class='progress-bar'>
<!-- Loading bar markup here -->
</div>
</div>
<div v-else class='content'>
<table>
<!-- Content -->
<tr v-for="log in logs">
<td>{{log.timestamp}}</td>
<td>{{log.event}}</td>
</tr>
</table>
</div>
Then in the script part of the template:
export default {
data() {
return: {
loading: true,
logs: [],
message: ''
};
},
methods: {
fetchLogs() {
// using vue-resource / ajax library like axios
this.$http.get('/api/logs').then((logs) => {
if (logs) {
this.logs = logs;
setTimeout(() => {
this.loading = false;
}, 1000);
} else {
this.message = 'No logs to display';
this.loading = false;
}
});
}
},
mounted() {
this.fetchLogs();
}
};
Using this method, you can also bind classes to the elements to create smooth CSS transitions.
Vue already has a v-cloak
directive built in, you just need to add the relevant css class:
[v-cloak] {
display: none;
}
And then apply it to your element like so:
<div v-cloak>
{{message}}
</div>
Here's the JSFiddle: https://jsfiddle.net/2jbe82hq/
If you remove v-cloak
in that fiddle you will see the mustached {{message}}
before the instance has been mounted.
If you want to display a loader
while you retrieve data from your server, then you combine a boolean flag with v-if
to show and hide the loader:
var vm = new Vue({
el: "#app",
created(){
this.$http.get('url').then(response => {
// set loader to false
this.loading = false;
});
},
data: {
message: 'Hello Vue!',
loading: true
}
});
You can then do:
<div v-if="loading">
Loading...
</div>
<div v-else>
{{message}}
</div>
Here's the JSFiddle for that: https://jsfiddle.net/fa70phLz/
It's also possible to use a loading
class as well and then use v-bind:class
to apply and remove the class based on the flag, which is useful if you want to overlay the entire page with a loader
.
<div :class="{'loading': loading}"></div>