How to display a "loading" animation while a lazy-loaded route component is being loaded?
You can use navigation guards to activate/deactivate a loading state that shows/hides a loading component:
If you would like to use something like "nprogress" you can do it like this:
http://jsfiddle.net/xgrjzsup/2669/
const router = new VueRouter({
routes
})
router.beforeEach((to, from, next) => {
NProgress.start()
next()
})
router.afterEach(() => {
NProgress.done()
})
Alternatively, if you want to show someting in-place:
http://jsfiddle.net/h4x8ebye/1/
Vue.component('loading',{ template: '<div>Loading!</div>'})
const router = new VueRouter({
routes
})
const app = new Vue({
data: { loading: false },
router
}).$mount('#app')
router.beforeEach((to, from, next) => {
app.loading = true
next()
})
router.afterEach(() => {
setTimeout(() => app.loading = false, 1500) // timeout for demo purposes
})
Then in the template:
<loading v-if="$root.loading"></loading>
<router-view v-else></router-view>
That could also be easily encapsulated in a very small component instead of using the $root
component for the loading state.
For what it's worth, I'll share what I ended up doing for my situation.
I'm using Vuex so it was easy to create an app-wide "loading" state which any component can access, but you can use whatever mechanism you want to share this state.
Simplified, it works like this:
function componentLoader(store, fn) {
return () => {
// (Vuex) Loading begins now
store.commit('LOADING_BAR_TASK_BEGIN');
// (Vuex) Call when loading is done
const done = () => store.commit('LOADING_BAR_TASK_END');
const promise = fn();
promise.then(done, done);
return promise;
};
}
function createRoutes(store) {
const load = fn => componentLoader(store, fn);
return [
{
path: '/foo',
component: load(() => import('./components/foo.vue')),
},
{
path: '/bar',
component: load(() => import('./components/bar.vue')),
},
];
}
So all I have to do is wrap every () => import()
by my load()
function which takes care of setting the loading state. Loading is determined by observing the promise directly instead of relying on router-specific before/after hooks.