最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - How do I create a splash screen in VueJS? - Stack Overflow

programmeradmin4浏览0评论

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);
});

Vueponent('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>

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>
Share Improve this question edited Jan 24, 2019 at 22:49 Al-76 asked Jan 24, 2019 at 22:21 Al-76Al-76 1,8686 gold badges26 silver badges46 bronze badges 1
  • 1 Do it outside of vue, so it can load without waiting for vue to load and it will look nicer. And then when vue loads, just remove element from DOM. – ljubadr Commented Jan 24, 2019 at 23:15
Add a comment  | 

3 Answers 3

Reset to default 15

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.

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

At beginning show fullscreen splash (with class binding listens for loadedApp). When vuejs mounted, (or your any other process completed then, change data loadedApp = true. Then fadeoutHide style will run and hides your splash

<div class="fullscreen-splash" :class="{fadeoutHide:loadedApp}">
       // splash logo etc
</div> 

data() {
 return {
  loadedApp: false
  }
 },
mounted() {
  this.loadedApp = true
 } 

.fadeoutHide {
  animation: fadeoutHide .5s forwards;
}
@keyframes fadeoutHide {
  to {
    opacity: 0;
    visibility: hidden;
  }
}
发布评论

评论列表(0)

  1. 暂无评论