Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I create a splash screen in VueJS?

I am trying to create a splash screen (loading-screen) in Vue JS that after a few seconds fades away, revealing my defaut view. I have tried several approaches but just can't get any to work. The closest is this example on CodePen But ideally the component wouldn't be inside main.js and instead inside its own component. Despite that the below code won't work.

My main.js is as below:

import Vue from "vue";
import App from "./App.vue";
import router from "./router";
import store from "./store";

Vue.config.productionTip = false;

// FILTERS
Vue.filter('snippet', function(value) {
    return value.slice(0,100);
});

Vue.component('loading-screen', {
  template: '<div id="loading">Loading...</div>'
})

new Vue({
  router,
  store,
  render: h => h(App),
  data: {
    isLoading: true
  },
  mounted () {
    setTimeout(() => {
      this.isLoading = false
    }, 3000)
  }
}).$mount("#app");

and my App.vue is as follows

<template>
  <div id="app">

    <loading-screen v-if="isLoading"></loading-screen>

    <Top/>
    <router-view/>
    <PrimaryAppNav/>

  </div>
</template>


<script>

import Top from './components/Top.vue'
import PrimaryAppNav from './components/PrimaryAppNav.vue'


export default {
  name: 'app',
  components: {
    Top,
    PrimaryAppNav
  }
}
</script>
like image 695
Al-76 Avatar asked Oct 20 '25 04:10

Al-76


2 Answers

A LoadingScreen.vue component could look like this:

<template>
  <div :class="{ loader: true, fadeout: !isLoading }">
    Loading ...
  </div>
</template>

<script>
export default {
  name: "LoadingScreen",
  props: ["isLoading"]
};
</script>

<style>
.loader {
  background-color: #63ab97;
  bottom: 0;
  color: white;
  display: block;
  font-size: 32px;
  left: 0;
  overflow: hidden;
  padding-top: 10vh;
  position: fixed;
  right: 0;
  text-align: center;
  top: 0;
}

.fadeout {
  animation: fadeout 2s forwards;
}

@keyframes fadeout {
  to {
    opacity: 0;
    visibility: hidden;
  }
}
</style>

Be aware that the loader needs to be aware if loading is done to be able to fade out. You need to check that in your App as well, so it's not showing while it still needs to prepare data. Otherwise, information from the app part in the background could be leaking (for example scrollbars might be visible on the LoadingScreen). So App.vue could have a template like this:

<template>
  <div id="app">
    <LoadingScreen :isLoading="isLoading" />
    <div v-if="!isLoading">
      ...your main content here...
    </div>
  </div>
</template>

If you want to have the LoadingScreen divs to disappear completely, you need to manage the state of the fadeout animation in the App.vue itself, making it a bit more complicated (I'd probably use two props for LoadingScreen then: isLoading and fadeout, where fadeout is a callback that gets called in LoadingScreen as soon as the fadeout animation is complete).

I have prepared a codesandbox for you with the state management inside the LoadingScreen.

like image 146
Narigo Avatar answered Oct 22 '25 19:10

Narigo


This is a working App.vue with a splash screen:

<template>
    <div id="app">
        <v-app :light="!nav.dark" :dark="nav.dark">
            <transition name="slide-fade" mode="out-in">
                <router-view></router-view>
            </transition>
        </v-app>
        <div v-if="loading" style="position:absolute; width: 100%; height:100%; top:0; left:0; z-index:10000; background-color:white">
            <div style="margin-left: auto; margin-right: auto">
                Loading...
            </div>
        </div>
    </div>
</template>

<script>
    export default {
        name: "app",
        data: () => ({
            loading: true
        }),
        mounted() {
            setTimeout(() => {
                this.loading = false
            }, 3000)
        }
    }
</script>

Note that there is a z-index trick and mounted is in App component. You can of course create a component just for loading, so it will become:

App.vue

<template>
    <div id="app">
        <v-app :light="!nav.dark" :dark="nav.dark">
            <transition name="slide-fade" mode="out-in">
                <router-view></router-view>
            </transition>
        </v-app>
        <loader v-if="loading"/>
    </div>
</template>

<script>
    import Loader from "./Loader"

    export default {
        name: "app",
        data: () => ({
            loading: true
        }),
        mounted() {
            setTimeout(() => {
                this.loading = false
            }, 3000)
        }
    }
</script>

Loader.vue

<template>
    <div style="position:absolute; width: 100%; height:100%; top:0; left:0; z-index:10000; background-color:white">
        <div style="margin-left: auto; margin-right: auto">
            Loading...
        </div>
    </div>
</template>

<script>
    export default {
        name: "loader"
    }
</script>

After that, I strongly suggest that you use dynamic components for your router components, Top and PrimaryAppNav. Like that they will load during your splash screen. You will find how to do that very easily in my answer in this thread (only section 2 is relevant for you): here

like image 39
Slim Avatar answered Oct 22 '25 19:10

Slim



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!