簡體   English   中英

如何在加載延遲加載的路由組件時顯示“加載”動畫?

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM