How to create a Pre-Loading/ Splash Screen in Nuxt.js before the app starts? - vue.js

I have tried to add a loader as shown in the nuxt.js documentation in between the routes but its not work. But I'm not able to add a splash screen before the app starts.
Code snippet in my components/loading.vue
<template>
<div v-if="loading" class="loading-page">
<p>Loading...</p>
</div>
</template>
<script>
export default {
data: () => ({
loading: false
}),
methods: {
start(){
this.loading = true
},
finish(){
this.loading = false
}
}
}
</script>
In nuxt.js.config
export default {
...
loading: '~/components/loading.vue'
...
}

As far as I know, you can't use a Vue component as a loading indicator for your your Nuxt app.
You will have to create an HTML document instead. This HTML document does not have to have an <html>, <head> or <body>. It just has to be the splash screen you want to show.
Here's how I did it:
Create an html document ~/assets/loading.html
Add the following to nuxt.config.js file.
loadingIndicator: {
name: '~/assets/loading.html'
}
Save and reload your page, you should now have a custom loading indicator / splash screen.
Example HTML file:
Here's a very simple file to show a splash screen image, when loading a nuxt app.
<div style="height: 100vh; width: 100vw; display: flex; align-items: center; justify-content: center; flex-direction: column; background-color: #004066; margin-left: -8px; margin-top: -8px; overflow: hidden;">
<img width="90%" src="<%= options.img %>">
</div>
NOTE:
Pay attention to <%= options.img %>. I'm making use of options, which can be defined in the nuxt.config.js simply by adding more keys to loadingIndicator, an example can be seen below.
loadingIndicator: {
name: '~/assets/loading.html',
img: '/loading.gif'
}
NOTE 2:
When accessing assets such as images in the loading indicator, you will have to put them in the /static folder.
Documentation: https://nuxtjs.org/docs/2.x/features/loading#custom-indicators
Official examples: https://github.com/nuxt/nuxt.js/tree/dev/packages/vue-app/template/views/loading

Related

Vue 3: how to change body background color only in specific page

with vue 3 i need to change the body background color only when i visit a signin page.
My index.html is:
<body class="body">
<div id="app"></div>
<!-- built files will be auto injected -->
</body>
How can i change the body background color from a component or from vue router?
In the App component you can put a conditional class on the top level element if the route matches your desired route. As long as your top level element is full height and width of the body.
<template>
<div class="background" :class="{ otherColor: isSignIn }">
<div id="app"></div>
</div>
</template>
<script>
export default {
computed: {
isSignIn() {
return this.$route.path === '/signIn';
}
}
}
</script>
<style>
.background {
height: 100vh;
width: 100vw;
background-color: #ffffff;
}
.otherColor {
background-color: #d4d4d4; // whatever background color you want.
}
</style>

Vuex Vue How to print child component without render it on parent component

I have a button on a summary page that #click will print a completed from that is not being rendered on that specific instance.
what is the best practice to print a component without having to render it on the active page?
I tried rendering the component on the page with visibility: hidden; so that the component renders then I can click the button to window.print()but this seems like a hack and not the best practice plus it adds a huge empty space to my instance.
I need a way to print the form (component) without actually rendering it on the page.
How do I solve the problem?
Take a look at #media features (#media print in your case). Just create a CSS class that will always apply display: none;, except when a browser in print mode.
Vue.component('my-component', { template: '<h1 class="print">Hello World</h1>' }, )
new Vue({
el: "#app"
})
.print {
display: none;
}
#media print {
.print {
display: initial;
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<my-component></my-component>
</div>

VueJS + Nuxtjs Unexpected Token 'export'

So i have this code as my index page and It was working, but a couple minutes later it just stopped.
the error is:
SyntaxError
Unexpected token export
Within the script section, If i remove my import then the error will go away, but I need to import it and use it. It was working with the package being imported, but I have looked this code up and down I have no idea what the heck is going on.
Anyone have any suggestions? Am I dumb and have missed something so simple?
<template>
<section class='container'>
<img class='my-4' src="~/assets/images/carousel/1.png" alt="card" />
<div class='text-center mx-auto my-4'>
<button> Send a card </button>
<p class='subtle my-4'> Or </p>
<button class='btn-blue'> Open a card </button>
</div>
<div id="qrcode"></div>
</section>
</template>
<script>
import qrcode from 'qrcode-generator-es6'; <<<<<<<<< SYNTAX ERROR AROUND HERE
export default{
data : function(){
return {};
},
methods : {
},
mounted : function(){
const qr = new qrcode(0, 'M');
qr.addData('https://app.voxicard.com/?v=vx-9FEFCA66-F592-4FF5-97B8-93B2FD78666D');
qr.make();
document.getElementById('qrcode').innerHTML = qr.createSvgTag({
margin : 0,
cellColor : function(){
return "#48658B";
},
});
},
};
</script>
<style>
#qrcode {
width: 200px;
height: 200px;
background-color: red;
}
img {
display: block;
max-height: 500px;
text-align: center;
margin: auto;
}
button {
font-size: 125%;
}
</style>
In your build property in nuxt.config.js you'll need to add a transpile block that targets this library:
build: {
transpile: [
'qrcode-generator-es6'
]
}
This is due to the fact that nuxt expects libraries to export as CJS modules and not ES6 modules.
In nuxt.config.js replace export default { on module.exports = {

VueJS single file component briefly showing SVG unstyled

I have a really simple Vue single-file component (using Vue 2.4.2) that includes an SVG image using a set of predefined SVG symbols and work perfectly.
I notice that the icon is briefly shown unstyled before the component (non-scoped) style is applied. Important to note that:
When including the scss in our main .scss file, the problem does not occur
Using v-cloak with has no effect
Occurs on latest Chrome, FF and Safari (MacOS)
Q: I can obviously use the workaround of including it in the main scss file, but I was wondering if this is SVG-styling specific or if a delay is normal when using component-style?
My component (additional scss omitted):
<template>
<i class="icon" v-if="symbol" :class="{'icon-spin': spinning}">
<svg>
<use v-bind:xlink:href="symbol"></use>
</svg>
</i>
</template>
<script>
export default {
name: 'Icon',
props: {
icon: {type: String},
spinning: {type: Boolean, default: false}
},
computed: {
symbol () {
return this.icon ? '#' + this.icon : ''
}
}
}
</script>
<style lang="scss">
#import '../../style/variables';
.icon {
display: inline-block;
width: $icon-size;
height: $icon-size;
line-height: 1;
svg {
width: 100%;
height: 100%;
fill: currentColor;
}
...

Check if everything (including video) is loaded in Vue?

I have a Vue project that is getting a little large due to an embedded html5 video and am wondering how to tackle the loading issue for this site.
Is there a way to know if everything is loaded in Vue so I can show a loading screen before everything is ready? And does this loading take into account of assets loading like images, videos, etc?
If you want to wait for the rest of the webpage to finish loading before displaying the video, you can wait until the window has loaded (load event) and then display the video via v-if.
Here's some additional things to consider (you're using webpack, right?):
Code splitting
If your JS bundle is getting too big, you can split it into smaller chunks and the webpack runtime will download the chunks asynchronously on demand.
I like to split my vendor code into a separate chunk, as well as split off some router components like this:
{
path: 'foo',
component: () => import('./components/foo.vue'),
}
See Code Splitting (Webpack docs) and Async Components (Vue docs) for more info.
Loading page
Your webpage will initially appear blank while the browser is downloading the HTML and JS assets before the Vue app has been bootstrapped. During this time, you can display whatever plain HTML content you want, then mount the root Vue component over the loading HTML.
const App = {
template: '<div>My App</div>',
};
function bootstrap() {
new Vue({
el: '#app',
render: h => h(App),
});
}
// Simulate loading
setTimeout(bootstrap, 2000);
body {
font-family: sans-serif;
}
#keyframes loading-anim {
from { opacity: 1; }
to { opacity: 0.3; }
}
.loading {
position: fixed;
left: 0;
top: 0;
right: 0;
bottom: 0;
display: flex;
align-items: center;
justify-content: center;
text-align: center;
font-size: 40px;
color: #888;
letter-spacing: -0.05em;
font-weight: bold;
animation: loading-anim 1s ease-in-out alternate infinite;
}
<div id="app">
<!-- Put whatever loading HTML content here -->
<div class="loading">LOADING</div>
</div>
<script src="https://rawgit.com/vuejs/vue/dev/dist/vue.js"></script>