[英]Is there a way to check if a lazy-loaded component (with React.Lazy) has finished loading?
[英]How to display a "loading" animation while a lazy-loaded route component is being loaded?
我已使用 webpack 的代碼拆分功能將我的應用程序拆分為多個塊,這樣當用戶訪問我的網頁時,就不會下載整個應用程序包。
某些路由所需的塊可能相當大,並且可能需要相當長的時間來下載。 這很好,除非用戶在單擊內部鏈接時不知道頁面實際上正在加載,所以我需要以某種方式顯示加載動畫或其他東西。
我的路由器是這樣配置的:
[
{
path: '/',
component: () => import(/* webpackChunkName: 'landing' */ './landing.vue'),
},
{
path: '/foo',
component: () => import(/* webpackChunkName: 'main' */ './foo.vue'),
},
{
path: '/bar',
component: () => import(/* webpackChunkName: 'main' */ './bar.vue'),
},
]
Vue.js 指南中的高級異步組件展示了如何在解析組件時顯示特定的“加載”組件——這正是我所需要的,但它也說:
請注意,當在 vue-router 中用作路由組件時,這些屬性將被忽略,因為異步組件是在路由導航發生之前預先解析的。
如何在 vue-router 中實現這一點? 如果這是不可能的,那么延遲加載的組件對我來說幾乎毫無用處,因為它會給用戶帶來糟糕的體驗。
您可以使用導航守衛來激活/停用顯示/隱藏加載組件的加載狀態:
如果你想使用類似“nprogress”的東西,你可以這樣做:
http://jsfiddle.net/xgrjzsup/2669/
const router = new VueRouter({
routes
})
router.beforeEach((to, from, next) => {
NProgress.start()
next()
})
router.afterEach(() => {
NProgress.done()
})
或者,如果您想就地展示一些東西:
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
})
然后在模板中:
<loading v-if="$root.loading"></loading>
<router-view v-else></router-view>
這也可以很容易地封裝在一個非常小的組件中,而不是使用$root
組件來加載狀態。
對於它的價值,我將分享我最終為我的情況所做的事情。
我正在使用 Vuex,因此很容易創建任何組件都可以訪問的應用程序范圍的“加載”狀態,但您可以使用任何想要共享此狀態的機制。
簡化后,它的工作原理如下:
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')),
},
];
}
所以我所要做的就是用我的load()
函數包裝每個() => import()
,該函數負責設置加載狀態。 加載是通過直接觀察 Promise 來確定的,而不是依賴於特定於路由器的 before/after 鈎子。
您可以在 vuejs 的一個項目中將此代碼用於 gobel 路由
const router = new Router({
routes: [
{ path: '/', name: 'home', component: Home },
{ path: '/about', name: 'about', component: About }
]
})
router.beforeResolve((to, from, next) => {
// If this isn't an initial page load.
if (to.name) {
// Start the route progress bar.
NProgress.start()
}
next()
})
router.afterEach((to, from) => {
// Complete the animation of the route progress bar.
NProgress.done()
})
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.