How do I hide the VueJS syntax while the page is loading?
Javascriptvue.jsJavascript Problem Overview
maybe this is a trivial question.
so, when I run my vuejs application on browser with enables throttling download speed (sets to low connection). I got unfinished vue syntax output in browser.
I know we can trick this out with showing loading image before entire page has loaded, but it's there any best solution to fix this?
Javascript Solutions
Solution 1 - Javascript
You can use the v-cloak directive, which will hide the Vue instance until the compilation finishes, if you combine it with the right CSS.
HTML:
<div v-cloak>{{ message }}</div>
CSS:
[v-cloak] { display: none; }
Solution 2 - Javascript
I attached the following codepen. You can see the difference with and without v-cloak
.
<div id="js-app">
[regular]Hold it... <span>{{test}}</span><br/>
[cloak]Hold it... <span v-cloak>{{test}}</span>
</div>
Solution 3 - Javascript
As suggested by others using v-cloak is proper solution. However as @ DelightedD0D mentioned it IS clunky. Simple solution is to add some CSS in the pseudo selector ::before
of v-cloak
directive.
In your sass/less file something along the lines of
[v-cloak] > * { display:none; }
[v-cloak]::before {
content: " ";
display: block;
position: absolute;
width: 80px;
height: 80px;
background-image: url(/images/svg/loader.svg);
background-size: cover;
left: 50%;
top: 50%;
}
Of course you'd need to provide a valid and accessible path to loader image. It will render something like.
Hope it helps.
Solution 4 - Javascript
Using v-cloak
directive you can hide un-compiled mustache bindings until vue instance is done compiling. You must use the CSS block to hide it until compiled.
HTML:
<div v-cloak>
{{ vueVariable }}
</div>
CSS:
[v-cloak] {
display: none;
}
This <div>
will not be visible until the compilation is completed.
You can see this link Hide elements during loading using v-cloak
for better understating.
Solution 5 - Javascript
Don't include any vuejs syntax in the HTML file:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<title>My Super app</title>
</head>
<body>
<div id="app"></div>
<script src="/app.js"></script>
</body>
</html>
In your main JavaScript, you can:
import Vue from 'vue'
import App from './App'
new Vue({
el: '#app',
components: { App },
template: '<App/>'
})
See the vuetify webpack template for reference.
Another solution is to use:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<title>My Super app</title>
</head>
<body>
<div id="app" is="App"></div>
<script src="/app.js"></script>
</body>
</html>
With:
import Vue from 'vue'
import App from './App'
Vue.component("App", App);
const app = new Vue({});
window.addEventListener("load", async () => {
app.$mount("#app")
})
Solution 6 - Javascript
Putting everything inside a <template>
worked well for me.
The content is hidden until rendered by Vue.
<!-- index.html -->
<div id="app">
<template>
<span class="name">{{ name.first }} {{ name.last }}</span>
</template>
</div>
/* index.js */
new Vue({
el: '#app',
data: {
name: { first: 'David', last: 'Davidovich'}
}
});
Solution 7 - Javascript
**html**
<div v-cloak>{{ message }}</div>
**css**
[v-cloak] { display: none; }
Solution 8 - Javascript
Use <v-cloak>
to hide your Vue code before binding data to relevant places. It's actually located in a place on Vue documentation that anyone might miss it unless you search for it or read thoroughly.
Solution 9 - Javascript
You could move any rendering to a simple wrapper component. The VueJS initialisation e.g. new Vue(....) shouldn’t contain any HTML apart from that single wrapper component.
Depending on setup you could even have <app>Loading...</app>
where app is the wrapper component with any loading HTML or text in between which is then replaced on load.
Solution 10 - Javascript
Yep, you can use v-cloak
, I like use spinkit, is a great library with only CSS, check a simple example:
var vm = null;
setTimeout(function() {
vm = new Vue({
el: '#app',
data: {
msg: 'Is great, using: ',
url: 'http://tobiasahlin.com/spinkit/'
}
});
}, 3000);
#app .sk-rotating-plane,
[v-cloak] > * { display:none }
body{
background: #42b983;
color: #35495e;
}
#app[v-cloak] .sk-rotating-plane {
display:block;
background-color: #35495e;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.2.6/vue.min.js"></script>
<link rel="stylesheet" type="text/css" href="https://cdn.rawgit.com/tobiasahlin/SpinKit/master/css/spinkit.css">
<div id="app" v-cloak>
<div class="sk-rotating-plane"></div>
<h1>Vue with c-cloak</h1>
<p>
{{ msg }}
<a :href='url'>{{ url }}</a>
<p>
</div>
Link:
Solution 11 - Javascript
For those who use v-cloak in a view with multiple Laravel Blade files and it's not working, try to use the v-cloak on the parent blade file rather than in any child blade file.
Solution 12 - Javascript
I prefer using v-if
with a computed property that checks if my data is ready, like this:
<template>
<div v-if="shouldDisplay">
{{ variableName }}
</div>
<div v-else>
Here you can insert a loader
</div>
</template>
<script>
export default {
name: 'Test',
data() {
return {
variableName: null,
};
},
computed() {
shouldDisplay() {
return this.variableName !== null;
}
},
mounted() {
this.variableName = 'yes';
},
};
</script>
In this way it's easier to show a loader only if the data is not ready (using v-else
).
In this particular case v-if="variableName"
would work as well, but there can be more complicated scenarios.