You might not know the v-cloak directive as it happens to be somewhere in the docs where you probably don’t pay attention to it. Until that day where you have a use case.
HTML rendering phases
What can be annoying with Vue.js is that the HTML elements are present in your page before Vue.js reads and compiles it.
Note : I am referring to simple use cases where you render components in an existing app, not SPA setups.
<html>
<body>
<div id="app">
<div>
Hello {{ name }}
</div>
</div>
<script src="vue.min.js"></script>
<script>
new Vue({
el: '#app',
data () {
return {
name: 'Simon'
}
}
})
</script>
</body>
</html>
In this example, for a brief moment, the whole content of the <div id="app"> element will be rendered in the browser.
It’s only after Vue.js core and the content of the <script> tag are loaded that it will be processed and compiled using the data provided.
This “brief moment” still gives users a poor experience, and its duration depends on the user’s bandwidth. During this time, they can see the mustache expression Hello {{ name }}. Needless to say there is probably more templating in your app than in this simple example.
Note : In Chrome’s developer tools, you can simulate a slow bandwidth in the “Network” tab (look for “throttling” options).
The v-cloak directive
Quoting the docs :
This directive will remain on the element until the associated Vue instance finishes compilation.
Meaning that we can add some CSS to hide it before the component is compiled.
<div id="app">
<div v-cloak>
Hello {{ name }}
</div>
</div>
<style>
[v-cloak] {
display: none;
}
</style>
Refresh and see the magic of Vue.js operating once again.
No more excuse for this flashing HTML mess on the startup of your apps.
How about single-page apps ?
At the beginning of this post I said that I was not referring to single-page apps. That’s not 100% true.
When an SPA starts up, there is some HTML that is sent to the user. It is the content of index.html. It probably doesn’t contain anything but the <div id="whatever"> that you use as root element. But if it does, make sure you have used v-cloak to prevent the browser from rendering its content.
Links
- Vue.js docs :
v-cloakdirective